{ config, pkgs, options, lib, ... }: let # Import home manager homeManager = fetchTarball "https://github.com/nix-community/home-manager/archive/release-24.05.tar.gz"; # IPs netInt = ''eno1''; localSpan = ''10.0.0''; serverIP = ''${localSpan}.2''; pcIP = ''${localSpan}.3''; vmIP = ''${localSpan}.4''; # Secrets and passwords secrets = import ./secrets.nix; in { # Import other nix files and firmware imports = [ ./hardware-configuration.nix ./jimbo.nix "${homeManager}/nixos" # Mail server import (fetchTarball "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-24.05/nixos-mailserver-nixos-24.05.tar.gz" ) ]; # Allow unfree packages nixpkgs.config.allowUnfree = true; # Allow flakes (I have no clue how they work yet) nix.settings.experimental-features = [ "nix-command" "flakes" ]; # Allow unfree firmware hardware.enableRedistributableFirmware = true; # Choose Grub as the bootloader boot = { loader.systemd-boot = { enable = true; netbootxyz.enable = true; }; }; # Enable a permissioning system security = { sudo.enable = false; doas = { enable = true; extraRules = [ # Give wheel root access, allow persistant session { groups = [ "wheel" ]; keepEnv = true; persist = true; } ]; }; }; # Enable the ZSH shell programs.zsh.enable = true; # Disable Nano programs.nano.enable = false; # Define user account. users.users.jimbo = { isNormalUser = true; hashedPassword = secrets.jimboAccPass; openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDLe/HioxCOkszFQdm1vb3ZwuzLzsOThqHNvEI4IXeXZ JimPhone" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJPjBdQrL23pDbcsNCLMvJhcNF7+u95ZV7o1QemOmegf jimbo@JimNixPC" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPeqiMCRXtpoP+BvKBmzvkL7oLKKCmbfdaQIF3yk/S8I jimbo@DV-JHAMPTON-NIXOS" ]; extraGroups = [ "wheel" "docker" "nfsShare" ]; uid = 1000; shell = pkgs.zsh; }; # Add service users to extra groups users.users = { nginx = { extraGroups = [ "turnserver" "virtualMail" ]; isSystemUser = true; }; nextcloud = { extraGroups = [ "nfsShare" ]; isSystemUser = true; }; }; # Define custom groups users.groups = { nfsShare = {}; }; # Installed programs to the system profile. environment.systemPackages = with pkgs; [ # Essential system tools git parted mdadm ]; # Define timezone and networking settings time.timeZone = secrets.timeZone; networking = { hostName = "JimNixServer"; # Choose networking method dhcpcd.enable = true; wireless.enable = false; # Configure firewall firewall = { allowPing = false; allowedTCPPorts = [ 80 443 # Nginx 25565 19132 5657 # Pufferpanel 2299 # Gitea SSH 3478 5349 # Coturn ]; allowedTCPPortRanges = [ { from = 8100; to = 8150; } # Azuracast ]; allowedUDPPorts = [ 25565 19132 # Minecraft Voicechat and Bedrock 3478 5349 # Coturn UDP ]; allowedUDPPortRanges = [ { from = 49000; to = 50000; } # Coturn range ]; # Add extra input rules using nftables extraInputRules = '' ip saddr ${localSpan}.0/24 tcp dport 2049 accept comment "Accept NFS" ip saddr ${localSpan}.0/24 udp dport 53 accept comment "Accept DNS" ip saddr { ${pcIP}, ${secrets.lunaIP}, ${secrets.cornIP}, ${secrets.vertIP} } tcp dport { 1935, 1945 } accept comment "Accept RTMP" ''; }; # Enable nftables and forwarding nftables = { enable = true; tables = { forwarding = { family = "ip"; content = '' chain PREROUTING { type nat hook prerouting priority dstnat; policy accept; tcp dport 2211 dnat to ${pcIP}:22 comment "SSH to PC" udp dport { 27005, 27015, 7777 } dnat to ${pcIP} comment "Games to PC" tcp dport { 58010, 57989, 57984 } dnat to ${pcIP} comment "Sunshine TCP to PC" udp dport { 57998, 57999, 58000 } dnat to ${pcIP} comment "Sunshine UDP to PC" tcp dport { 38010, 37989, 37984 } dnat to ${vmIP} comment "Sunshine TCP to VM" udp dport { 37998, 37999, 38000 } dnat to ${vmIP} comment "Sunshine UDP to VM" ip saddr ${secrets.cornIP} tcp dport { 9943, 9944 } dnat to ${vmIP} comment "ALVR TCP to VM" ip saddr ${secrets.cornIP} udp dport { 9943, 9944 } dnat to ${vmIP} comment "ALVR UDP to VM" } chain POSTROUTING { type nat hook postrouting priority 100; policy accept; oifname "${netInt}" masquerade } ''; }; }; }; }; # Boot with compatibility for IP forwarding boot.kernel.sysctl."net.ipv4.ip_forward" = 1; # Enable AppArmor security.apparmor.enable = true; # Enable all manner of services services = { # SSH openssh = { enable = true; settings = { LogLevel = "VERBOSE"; PermitRootLogin = "no"; PrintLastLog = "no"; PasswordAuthentication = false; }; ports = [ 2222 ]; }; # Login attempt lockout fail2ban = { enable = true; maxretry = 5; bantime = "5m"; ignoreIP = [ "${pcIP}" "${vmIP}" ]; }; # NFS server nfs.server = { enable = true; exports = '' /export/JimboNFS ${localSpan}.0/24(rw,no_subtree_check) ''; }; # DDClient for Dynamic IPs ddclient = { enable = true; protocol = "cloudflare"; use = "web, web=https://ipinfo.io/ip"; zone = "${secrets.jimDomain}"; username = "token"; passwordFile = "${pkgs.writeText "cloudflareapikey" secrets.flareApiKey}"; domains = [ "${secrets.jimDomain}" "*.${secrets.jimDomain}" "beta.${secrets.jimDomain}" "git.${secrets.jimDomain}" "john.${secrets.jimDomain}" "mc.${secrets.jimDomain}" "mx.${secrets.jimDomain}" "panel.${secrets.jimDomain}" "rtmp.${secrets.jimDomain}" ]; }; # Nginx reverse proxy nginx = { enable = true; package = (pkgs.nginx.override { modules = with pkgs.nginxModules; [ rtmp ]; }); recommendedTlsSettings = true; recommendedOptimisation = true; recommendedGzipSettings = true; recommendedProxySettings = true; virtualHosts = { # Homepage redirect "${secrets.jimDomain}" = { enableACME = true; addSSL = true; root = "/var/www/jimweb"; locations = { "/.well-known/matrix/client" = { extraConfig = '' default_type application/json; return 200 ' { "m.homeserver": { "base_url": "https://matrix.${secrets.jimDomain}" }, "m.identity_server": { "base_url": "https://matrix.org" }, "org.matrix.msc3575.proxy": { "url": "https://matrix.${secrets.jimDomain}" } }'; ''; }; "/.well-known/matrix/server" = { extraConfig = '' default_type application/json; return 200 '{"m.server": "matrix.${secrets.jimDomain}:443"}'; ''; }; }; }; # Nextcloud Proxy "cloud.${secrets.jimDomain}" = { enableACME = true; addSSL = true; locations."/" = { proxyWebsockets = true; extraConfig = " location /.well-known/carddav { return 301 $scheme://$host/remote.php/dav; } location /.well-known/caldav { return 301 $scheme://$host/remote.php/dav; } "; }; }; # Vaultwarden Proxy "warden.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:8222"; proxyWebsockets = true; }; }; # Recipes Proxy "recipes.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:5030"; proxyWebsockets = true; }; }; # Bluemap Proxy "bluemap.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:31010"; proxyWebsockets = true; }; }; # Gitea Proxy "git.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:3110"; proxyWebsockets = true; }; }; # Pufferpanel Proxy "panel.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:5010"; proxyWebsockets = true; }; }; # Matrix Proxy "matrix.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; locations = { "/".extraConfig = ''return 403;''; "/client".proxyPass = "http://127.0.0.1:8009"; "/_matrix".proxyPass = "http://127.0.0.1:8008"; "/_matrix/client/unstable/org.matrix.msc3575/sync".proxyPass = "http://127.0.0.1:8009"; "/_synapse/client".proxyPass = "http://127.0.0.1:8008"; }; }; # Element Proxy "chat.${secrets.jimDomain}" = { enableACME = true; addSSL = true; root = "${pkgs.element-web}"; }; # Coturn Proxy "turn.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; listen = [ { addr = "0.0.0.0"; port = 80; ssl = false; } ]; locations."/".proxyPass = "http://127.0.0.1:1380"; }; # Radio Proxy "radio.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:255"; proxyWebsockets = true; }; }; # Streaming proxy "live.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:8060"; proxyWebsockets = true; }; }; # Mail certificate proxy "mx.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:1390"; proxyWebsockets = true; }; }; # Add SSL to Lemmy "lemmy.${secrets.jimDomain}" = { enableACME = true; forceSSL = true; }; }; appendConfig = '' rtmp { server { listen 1935; chunk_size 4096; allow publish all; application stream { record off; live on; allow play all; hls on; hls_path /var/www/jimweb/streams/hls; hls_fragment_naming system; hls_fragment 3; hls_playlist_length 40; } } } ''; }; # Nextcloud server nextcloud = { enable = true; package = pkgs.nextcloud29; hostName = "cloud.${secrets.jimDomain}"; datadir = "/mnt/nextcloud"; https = true; config = { adminuser = "jimbo"; adminpassFile = "/mnt/nextcloud/password.txt"; }; settings = { trusted_proxies = [ "127.0.0.1" ]; trusted_domains = [ "cloud.${secrets.jimDomain}" ]; overwriteprotocol = "https"; # Mailserver settings mail_smtphost = "mx.${secrets.jimDomain}"; mail_domain = "${secrets.jimDomain}"; mail_from_address = "noreply"; mail_smtpauth = "true"; mail_smtpname = "noreply@${secrets.jimDomain}"; mail_smtppassword = secrets.noreplyPassword; mail_smtpmode = "smtp"; mail_smtpport = 587; }; }; # Vaultwarden password manager vaultwarden = { enable = true; config = { DOMAIN = "https://warden.${secrets.jimDomain}"; SIGNUPS_ALLOWED = false; ROCKET_ADDRESS = "127.0.0.1"; ROCKET_PORT = 8222; ROCKET_LOG = "critical"; # Smtp email SMTP_HOST = "mx.${secrets.jimDomain}"; SMTP_FROM = "Jimbo's Vaultwarden "; SMTP_FROM_NAME = "Vaultwarden"; SMTP_USERNAME = "noreply@${secrets.jimDomain}"; SMTP_PASSWORD = secrets.noreplyPassword; SMTP_SECURITY = "starttls"; SMTP_PORT = 587; SMTP_TIMEOUT = 15; }; }; # Recipes tandoor-recipes = { enable = true; port = 5030; }; # Gitea gitea = { enable = true; settings = { server = { DOMAIN = "git.${secrets.jimDomain}"; ROOT_URL = "https://git.${secrets.jimDomain}:443"; HTTP_PORT = 3110; SSH_PORT = 2299; START_SSH_SERVER = true; }; mailer = { ENABLED = true; SMTP_ADDR = "mx.${secrets.jimDomain}"; FROM = "Jimbo's Git "; USER = "noreply@${secrets.jimDomain}"; PASSWD = secrets.noreplyPassword; PROTOCOL = "smtps"; }; service.REGISTER_EMAIL_CONFIRM = true; }; }; # Pufferpannel for Minecraft pufferpanel = { enable = true; environment = { PUFFER_WEB_HOST = ":5010"; PUFFER_PANEL_SETTINGS_MASTERURL = "https://panel.${secrets.jimDomain}"; PUFFER_PANEL_EMAIL_PROVIDER = "smtp"; PUFFER_PANEL_EMAIL_HOST = "mx.${secrets.jimDomain}:587"; PUFFER_PANEL_EMAIL_FROM = "noreply@${secrets.jimDomain}"; PUFFER_PANEL_EMAIL_USERNAME = "noreply@${secrets.jimDomain}"; PUFFER_PANEL_EMAIL_PASSWORD = secrets.noreplyPassword; }; extraPackages = with pkgs; [ bash curl gawk gnutar gzip ]; package = pkgs.buildFHSEnv { name = "pufferpanel-fhs"; meta.mainProgram = "pufferpanel-fhs"; runScript = lib.getExe pkgs.pufferpanel; targetPkgs = pkgs': with pkgs'; [ icu openssl zlib ]; }; }; # MariaDB mysql = { enable = true; package = pkgs.mariadb; dataDir = "/var/lib/mysql"; initialDatabases = [ { name = "minecraft"; } ]; ensureUsers = [ { name = "minecraft"; ensurePermissions = { "minecraft.*" = "ALL PRIVILEGES"; }; } ]; }; # Owncast owncast = { enable = true; port = 8060; rtmp-port = 1945; listen = "0.0.0.0"; }; # Coturn for VC coturn = rec { enable = true; no-cli = true; no-tcp-relay = true; min-port = 49000; max-port = 50000; use-auth-secret = true; realm = "turn.${secrets.jimDomain}"; static-auth-secret = "will be world readable for local users :("; cert = "${config.security.acme.certs.${realm}.directory}/full.pem"; pkey = "${config.security.acme.certs.${realm}.directory}/key.pem"; }; # Synapse for Matrix clients matrix-synapse = with config.services.coturn; { enable = true; settings = { server_name = "${secrets.jimDomain}"; public_baseurl = "https://matrix.${secrets.jimDomain}"; suppress_key_server_warning = true; # Set the network config listeners = [{ # Client config port = 8008; bind_addresses = [ "::" "0.0.0.0" ]; resources = [ { compress = false; names = [ "client" "federation" ]; } ]; type = "http"; tls = false; x_forwarded = true; }]; # Enable smtp for password resets email = { notif_from = "Jimbo's Matrix "; smtp_host = "mx.${secrets.jimDomain}"; smtp_user = "noreply@${secrets.jimDomain}"; smtp_pass = secrets.noreplyPassword; enable_tls = true; smtp_port = 587; require_transport_security = true; }; # Disable registration without email registrations_require_3pid = [ "email" ]; # Allow only this range of emails allowed_local_3pids = [{ medium = "email"; pattern = "^[^@]+@jimbosfiles\\.com$"; }]; # Set the type of database database.name = "sqlite3"; # Allow account registration enable_registration = true; # General settings url_preview_enabled = true; max_upload_size = "50M"; report_stats = false; # Turn settings turn_uris = [ "turn:${realm}:3478?transport=udp" "turn:${realm}:3478?transport=tcp" ]; turn_shared_secret = static-auth-secret; turn_user_lifetime = "1h"; # Ratelimiting burst_count = 15; }; }; # Sliding sync proxy for Matrix matrix-sliding-sync = let matrixSecretFile = pkgs.writeText "matrixsecret" '' SYNCV3_SECRET=${secrets.matrixSecret} ''; in { enable = true; settings = { SYNCV3_SERVER = "https://matrix.${secrets.jimDomain}"; SYNCV3_BINDADDR = "0.0.0.0:8009"; }; environmentFile = "${matrixSecretFile}"; }; # Mastodon mastodon = { enable = true; localDomain = "social.${secrets.jimDomain}"; streamingProcesses = 4; configureNginx = true; smtp = { createLocally = false; host = "mx.${secrets.jimDomain}"; port = 587; authenticate = true; fromAddress = "Jimbo's Mastodon "; user = "noreply@${secrets.jimDomain}"; passwordFile = pkgs.writeText "smtp_pass.txt" secrets.noreplyPassword; }; }; # Lemmy forums lemmy = { enable = true; nginx.enable = true; database.createLocally = true; settings = { hostname = "lemmy.${secrets.jimDomain}"; email = { smtp_server = "mx.${secrets.jimDomain}:587"; smtp_login = "noreply@${secrets.jimDomain}"; smtp_from_address = "Jimbo's Lemmy "; smtp_password = secrets.noreplyPassword; tls_type = "starttls"; }; }; }; # Roundcube mail server roundcube = { enable = true; hostName = "mail.${secrets.jimDomain}"; extraConfig = '' $config['smtp_server'] = "tls://${config.mailserver.fqdn}"; $config['smtp_user'] = "%u"; $config['smtp_pass'] = "%p"; ''; }; # Snowflake proxy for Tor snowflake-proxy.enable = true; # Fix a nonbuilding issue logrotate.checkConfig = false; # Force the mailserver to use a different redis port redis.servers.rspamd.port = 1515; }; # Force Nginx to work and be able to read+write the hls path security.pam.services.nginx.setEnvironment = false; systemd.services.nginx.serviceConfig = { SupplementaryGroups = [ "shadow" ]; ReadWritePaths = [ "/var/www/jimweb/streams/hls/" ]; }; # Get certificates for Coturn security.acme = { acceptTerms = true; defaults.email = secrets.jimEmail; certs = { ${config.services.coturn.realm} = { group = "turnserver"; postRun = "systemctl restart coturn.service"; }; }; }; # Configure the Element web server nixpkgs.config.element-web.conf = { default_server_config = { "m.homeserver" = { base_url = "https://matrix.${secrets.jimDomain}"; server_name = "matrix.${secrets.jimDomain}"; }; }; branding = { #welcome_background_url = "https://staging.${secrets.jimDomain}/images/backgrounds/bloxelcom-sunset.jpg"; #auth_header_logo_url = "https://staging.${secrets.jimDomain}/images/logos/bloxelcom.png"; }; embedded_pages = { home_url = "https://www.${secrets.jimDomain}/"; }; disable_custom_urls = true; disable_guests = true; default_theme = "dark"; }; # Enable Docker virtualisation.docker = { enable = true; daemon.settings.log-driver = "json-file"; }; # Mail server mailserver = rec { enable = true; enableManageSieve = true; domains = [ "${secrets.jimDomain}" ]; fqdn = "mx.${secrets.jimDomain}"; certificateScheme = "acme-nginx"; localDnsResolver = false; redis.port = 1515; # A list of accounts. # Generate passwords with nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt' loginAccounts = { "noreply@${secrets.jimDomain}" = { hashedPasswordFile = pkgs.writeText "noreply" secrets.noreplyMailHash; sendOnly = true; }; "jimbo@${secrets.jimDomain}" = { hashedPasswordFile = pkgs.writeText "jimbo" secrets.jimboMailHash; aliases = [ "canada@${secrets.jimDomain}" "contact@${secrets.jimDomain}" ]; }; "lunamoonlight@${secrets.jimDomain}" = { hashedPasswordFile = pkgs.writeText "luna" secrets.lunaMailHash; aliases = [ "us@${secrets.jimDomain}" "contact@${secrets.jimDomain}" ]; }; "freecorn1854@${secrets.jimDomain}" = { hashedPasswordFile = pkgs.writeText "freecorn" secrets.freecornMailHash; aliases = [ "canada@${secrets.jimDomain}" "contact@${secrets.jimDomain}" ]; }; "tinyattack09@${secrets.jimDomain}" = { hashedPasswordFile = pkgs.writeText "tiny" secrets.tinyMailHash; }; }; }; # Determine the release version and allow auto-upgrades system.stateVersion = "23.11"; system.autoUpgrade.enable = false; }