{ config, pkgs, options, lib, ... }: let # Import home manager homeManager = fetchTarball "https://github.com/nix-community/home-manager/archive/release-24.05.tar.gz"; # Define domains and ips jimdomain = ''jimbosfiles.com''; bloxeldomain = ''bloxelcom.net''; # IPs localspan = ''192.168.2''; pc = ''${localspan}.10''; server = ''${localspan}.11''; vm = ''${localspan}.70''; # 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 (builtins.fetchTarball { url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-24.05/nixos-mailserver-nixos-24.05.tar.gz"; sha256 = "0clvw4622mqzk1aqw1qn6shl9pai097q62mq1ibzscnjayhp278b"; }) ]; # 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 = { kernelPackages = pkgs.linuxPackages_xanmod; loader = { grub = { efiSupport = true; device = "nodev"; }; }; }; # 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.jimboAccPassword; openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDLe/HioxCOkszFQdm1vb3ZwuzLzsOThqHNvEI4IXeXZ JimPhone" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEuCYrIZlD6LNpFh3XTYbXaPQWYysr1oZAX4DL3gF28l jimbo@DV-JHAMPTON" ]; extraGroups = [ "wheel" "docker" "musicFolder" "nfsShare" ]; uid = 1000; shell = pkgs.zsh; }; # Add service users to extra groups users.users = { nginx = { extraGroups = [ "turnserver" "virtualMail" ]; isSystemUser = true; }; nextcloud = { extraGroups = [ "nfsShare" "musicFolder" ]; isSystemUser = true; }; }; # Define custom groups users.groups = { nfsShare = {}; musicFolder = {}; }; # Installed programs to the system profile. environment.systemPackages = with pkgs; [ # Essential system tools git parted mdadm ]; # Define timezone and networking settings time.timeZone = "America/New_York"; networking = { # Set hostname hostName = "JimNixServer"; # Choose networking method dhcpcd.enable = true; wireless.enable = false; # Enable firewall passthrough firewall = { allowedTCPPorts = [ # NFS 2049 # Nginx 80 443 # Minecraft 25565 19132 # Pufferpanel sftp 5657 # Gitea SSH 2299 # Coturn 3478 5349 ]; allowedTCPPortRanges = [ # Also Azuracast { from = 8100; to = 8150; } ]; allowedUDPPorts = [ # Minecraft Voicechat and Bedrock 25565 19132 # Coturn again 3478 5349 ]; allowedUDPPortRanges = [ # Coturn { from = 49000; to = 50000; } ]; # Extra rules that cannot be done above extraCommands = # SSH and game servers from my PC '' iptables -t nat -A PREROUTING -p tcp -m tcp --dport 2211 -m comment --comment "SSH to PC" -j DNAT --to-destination ${pc} iptables -t nat -A PREROUTING -p udp -m udp --match multiport --dports 27005,27015,7777,29000 -m comment --comment "Games" -j DNAT --to-destination ${pc} '' + # Sunshine ports for PC and VM '' iptables -t nat -A PREROUTING -p tcp -m tcp --match multiport --dports 48010,47989,47984 -m comment --comment "PC Sunshine TCP" -j DNAT --to-destination ${pc} iptables -t nat -A PREROUTING -p udp -m udp --match multiport --dports 47998,47999,48000 -m comment --comment "PC Sunshine UDP" -j DNAT --to-destination ${pc} iptables -t nat -A PREROUTING -p tcp -m tcp --match multiport --dports 38010,37989,37984 -m comment --comment "VM Sunshine TCP" -j DNAT --to-destination ${vm} iptables -t nat -A PREROUTING -p udp -m udp --match multiport --dports 37998,37999,38000 -m comment --comment "VM Sunshine UDP" -j DNAT --to-destination ${vm} '' + # Set an IP firewall for RTMP '' iptables -N RTMPCHAIN iptables -A INPUT -p tcp -m tcp --match multiport --dports 1935,1945 -j RTMPCHAIN iptables -A RTMPCHAIN -s ${pc} -m comment --comment "Local PC" -j ACCEPT iptables -A RTMPCHAIN -s 71.87.124.226 -m comment --comment "Luna IP" -j ACCEPT iptables -A RTMPCHAIN -s 24.66.98.13 -m comment --comment "Freecorn IP" -j ACCEPT iptables -A RTMPCHAIN -j DROP '' + # Finalize forwarding '' iptables -t nat -A POSTROUTING -o eno1 -j MASQUERADE ''; # Remove the chain and such extraStopCommands = '' iptables -D INPUT -p tcp -m tcp --match multiport --dports 1935,1945 -j RTMPCHAIN iptables -F RTMPCHAIN iptables -X RTMPCHAIN ''; # Disallow pinging this server allowPing = false; }; }; # 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; ignoreIP = [ "${pc}" "${server}" "${vm}" ]; }; # NFS server nfs.server = { enable = true; exports = '' /export/JimboNFS ${localspan}.0/24(rw,no_subtree_check) ''; }; # 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 "${jimdomain}" = { enableACME = true; addSSL = true; locations."/" = { extraConfig = " return 301 https://social.${bloxeldomain}/@jimbo; "; }; }; # Nextcloud Proxy "cloud.${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.${jimdomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:8222"; proxyWebsockets = true; }; }; # Recipes Proxy "recipes.${jimdomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:5030"; proxyWebsockets = true; }; }; # Bluemap Proxy "bluemap.${jimdomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:31010"; proxyWebsockets = true; }; }; # Gitea Proxy "git.${jimdomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:3110"; proxyWebsockets = true; }; }; # Gitea Proxy "mc.${jimdomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:5010"; proxyWebsockets = true; }; }; # Matrix Proxy "matrix.${bloxeldomain}" = { enableACME = true; forceSSL = true; locations."/_matrix".proxyPass = "http://[::1]:8008"; locations."/_synapse".proxyPass = "http://[::1]:8008"; }; # Element Proxy "chat.${bloxeldomain}" = { enableACME = true; addSSL = true; root = "${pkgs.element-web}"; }; # Coturn Proxy "turn.${bloxeldomain}" = { enableACME = true; forceSSL = true; listen = [ { addr = "[::]"; port = 80; ssl = false; } { addr = "0.0.0.0"; port = 80; ssl = false; } ]; locations."/".proxyPass = "http://[::1]:1380"; }; # Radio Proxy "wbxdradio.${bloxeldomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:255"; proxyWebsockets = true; }; }; # Streaming proxy "live.${bloxeldomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:8060"; proxyWebsockets = true; }; }; # Mail certificate proxy "mx.${bloxeldomain}" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://127.0.0.1:1390"; proxyWebsockets = true; }; }; # Add SSL to Lemmy "lemmy.${bloxeldomain}" = { enableACME = true; forceSSL = true; }; # Staging Bloxel Proxy "staging.${bloxeldomain}" = { enableACME = true; addSSL = true; root = "/var/www/bloxelcomweb/landing-page/"; locations."/BloxelcomCable/hls" = { extraConfig = '' # Disable cache add_header Last-Modified $date_gmt; add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; if_modified_since off; expires off; etag off; # Allow serving m3u8 files types { application/vnd.apple.mpegurl m3u8; } ''; }; locations."/.well-known/matrix/client" = { extraConfig = '' default_type application/json; add_header Access-Control-Allow-Origin *; return 200 '{"m.server": "matrix.${bloxeldomain}:443"}'; ''; }; locations."/.well-known/matrix/server" = { extraConfig = '' default_type application/json; return 200 '{"m.server": "matrix.${bloxeldomain}:443"}'; ''; }; }; }; appendConfig = '' rtmp { server { listen 1935; chunk_size 4096; allow publish all; application stream { record off; live on; deny play all; hls on; hls_path /var/www/bloxelcomweb/landing-page/bloxelcom-cable/hls; hls_fragment_naming system; hls_fragment 3; hls_playlist_length 40; } application forward { record off; live on; allow play all; } } } ''; }; # Nextcloud server nextcloud = { enable = true; package = pkgs.nextcloud29; hostName = "cloud.${jimdomain}"; datadir = "/mnt/nextcloud"; https = true; config = { adminuser = "jimbo"; adminpassFile = "/mnt/nextcloud/password.txt"; }; settings = { trusted_proxies = [ "127.0.0.1" ]; trusted_domains = [ "cloud.${jimdomain}" ]; overwriteprotocol = "https"; # Mailserver settings mail_smtphost = "mx.${bloxeldomain}"; mail_domain = "${bloxeldomain}"; mail_from_address = "noreply"; mail_smtpauth = "true"; mail_smtpname = "noreply@${bloxeldomain}"; mail_smtppassword = secrets.noreplyPassword; mail_smtpmode = "smtp"; mail_smtpport = 587; }; }; # Vaultwarden password manager vaultwarden = { enable = true; config = { DOMAIN = "https://warden.${jimdomain}"; SIGNUPS_ALLOWED = false; ROCKET_ADDRESS = "127.0.0.1"; ROCKET_PORT = 8222; ROCKET_LOG = "critical"; # Smtp email SMTP_HOST = "mx.${bloxeldomain}"; SMTP_FROM = "noreply@${bloxeldomain}"; SMTP_FROM_NAME = "Vaultwarden"; SMTP_USERNAME = "noreply@${bloxeldomain}"; 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.${jimdomain}"; ROOT_URL = "https://git.${jimdomain}:443"; HTTP_PORT = 3110; SSH_PORT = 2299; START_SSH_SERVER = true; }; mailer = { ENABLED = true; SMTP_ADDR = "mx.${bloxeldomain}"; FROM = "noreply@${bloxeldomain}"; PASSWD = secrets.noreplyPassword; PROTOCOL = "smtp+starttls"; SMTP_PORT = 587; }; service.DISABLE_REGISTRATION = true; }; }; # Pufferpannel for Minecraft pufferpanel = { enable = true; environment = { PUFFER_WEB_HOST = ":5010"; PUFFER_PANEL_REGISTRATIONENABLED = "false"; PUFFER_PANEL_EMAIL_PROVIDER = "smtp"; PUFFER_PANEL_EMAIL_HOST = "mx.${bloxeldomain}:587"; PUFFER_PANEL_EMAIL_FROM = "noreply@${bloxeldomain}"; PUFFER_PANEL_EMAIL_USERNAME = "noreply@${bloxeldomain}"; 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 = "nextcloud"; } { name = "matrix"; } { name = "git"; } { name = "minecraft"; } ]; ensureUsers = [ { name = "nextcloud"; ensurePermissions = { "nextcloud.*" = "ALL PRIVILEGES"; }; }{ name = "matrix-synapse"; ensurePermissions = { "matrix.*" = "ALL PRIVILEGES"; }; }{ name = "gitea"; ensurePermissions = { "git.*" = "ALL PRIVILEGES"; }; }{ 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.${bloxeldomain}"; 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 = "${bloxeldomain}"; public_baseurl = "https://matrix.${bloxeldomain}"; 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 = "Bloxelcom's Matrix Homeserver "; smtp_host = "mx.${bloxeldomain}"; smtp_user = "noreply@${bloxeldomain}"; 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 = "^[^@]+@bloxelcom\\.net$"; }]; # 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; }; }; # Mastodon mastodon = { enable = true; localDomain = "social.${bloxeldomain}"; streamingProcesses = 4; configureNginx = true; smtp = { createLocally = false; host = "mx.${bloxeldomain}"; port = 587; authenticate = true; fromAddress = "noreply@${bloxeldomain}"; user = "noreply@${bloxeldomain}"; passwordFile = pkgs.writeText "smtp_pass.txt" secrets.noreplyPassword; }; }; # Lemmy forums lemmy = { enable = true; nginx.enable = true; database.createLocally = true; settings = { hostname = "lemmy.${bloxeldomain}"; email = { smtp_server = "mx.${bloxeldomain}:587"; smtp_login = "noreply@${bloxeldomain}"; smtp_from_address = "noreply@${bloxeldomain}"; smtp_password = secrets.noreplyPassword; tls_type = "starttls"; }; }; }; # Roundcube mail server roundcube = { enable = true; hostName = "mail.${bloxeldomain}"; 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; }; # Make Nginx not shit itself security.pam.services.nginx.setEnvironment = false; systemd.services.nginx.serviceConfig = { SupplementaryGroups = [ "shadow" ]; }; systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www/bloxelcomweb/landing-page/bloxelcom-cable/hls/" ]; # Get certificates for Coturn security.acme = { acceptTerms = true; defaults.email = "jimjam4real@gmail.com"; 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.${bloxeldomain}:443"; server_name = "matrix.${bloxeldomain}"; }; }; branding = { welcome_background_url = "https://staging.${bloxeldomain}/images/backgrounds/bloxelcom-sunset.jpg"; auth_header_logo_url = "https://staging.${bloxeldomain}/images/logos/bloxelcom.png"; }; embedded_pages = { home_url = "https://www.${bloxeldomain}/"; }; 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 = [ "${bloxeldomain}" ]; fqdn = "mx.${bloxeldomain}"; certificateScheme = "acme-nginx"; # A list of accounts. # Generate passwords with nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt' loginAccounts = { "noreply@${bloxeldomain}" = { hashedPasswordFile = pkgs.writeText "noreply" secrets.noreplySmtpHash; sendOnly = true; }; "jimbo@${bloxeldomain}" = { hashedPasswordFile = pkgs.writeText "jimbo" secrets.jimboSmtpHash; aliases = [ "canada@${bloxeldomain}" "contact@${bloxeldomain}" ]; }; "lunamoonlight@${bloxeldomain}" = { hashedPasswordFile = pkgs.writeText "luna" secrets.lunaSmtpHash; aliases = [ "us@${bloxeldomain}" "contact@${bloxeldomain}" ]; }; "freecorn1854@${bloxeldomain}" = { hashedPasswordFile = pkgs.writeText "freecorn" secrets.freecornSmtpHash; aliases = [ "canada@${bloxeldomain}" "contact@${bloxeldomain}" ]; }; "tinyattack09@${bloxeldomain}" = { hashedPasswordFile = pkgs.writeText "tiny" secrets.tinySmtpHash; aliases = [ "smallthing@${bloxeldomain}" ]; }; }; }; # Determine the release version and allow auto-upgrades system.stateVersion = "23.11"; system.autoUpgrade.enable = false; }