{ pkgs, inputs, lib, ... }: let home-manager = builtins.fetchTarball { url = "https://github.com/nix-community/home-manager/archive/release-24.11.tar.gz"; sha256 = "0c07xj74vsj37d3a8f98i9rhhhr99ckwlp45n40f0qkmigm3pk8s"; }; in { imports = [ ./hardware-configuration.nix (import "${home-manager}/nixos") #../../flakes/wishlist/wishlist.nix #../modules/server/nginx.nix #../modules/server/ssh.nix #../modules/server/fail2ban.nix ]; # override wishlist with the new cool one! #pkgs.config.packageOverrides = { # wishlist = inputs.wishlist.packages.x86_64-linux.wishlist; #}; nix.settings = { # make wheel group trusted users allows my "ae" user # to import packages not signed by a trusted key # (aka super duper easier to remote deploy) trusted-users = ["root" "@wheel"]; experimental-features = [ "nix-command" "flakes" ]; }; time.timeZone = "Australia/Brisbane"; i18n.defaultLocale = "en_US.UTF-8"; console = { font = "Lat2-Terminus16"; keyMap = "us"; }; # colmena deployment configuration deployment = { targetHost = "imbored.dev"; targetUser = "ae"; targetPort = 22; # the following line is unnecessary if using an ssh agent #sshOptions = ["-i /home/me/.ssh/id_hyrule"]; #keys = { # "imbored.dev" = { # # text, keyCommand, or keyFile must be set # # text = ""; # #keyCommand = [ "" ]; # keyFile = "/home/me/.ssh/id_hyrule"; # }; #}; buildOnTarget = false; # build locally then deploy }; # super duper minimum grub2 config boot.loader.grub = { enable = true; device = "/dev/vda"; }; networking = { hostName = "hyrule"; networkmanager.enable = true; firewall = { enable = true; allowedTCPPorts = [ 22 # sshd 80 # nginx # 143 # IMAP4 443 # nginx # 587 # SMTPS 2222 # forgejo ssh 2035 # debug (for my job) # 3000 (INTERNAL) forgejo # 3306 (INTERNAL) forgejo sqlite3 database 5000 # debug (for my job) # 8222 (INTERNAL) vaultwarden ]; }; }; # grant passwordless sudo to wheel group security.sudo.wheelNeedsPassword = false; users = { defaultUserShell = pkgs.bash; users = { # primary user ae = { isNormalUser = true; extraGroups = ["wheel" "networkmanager" "docker"]; shell = pkgs.bash; home = "/home/ae"; # TEMP: remove and replace with home-manager packages = with pkgs; [ ]; }; subspace = let # override wishlistBash = pkgs.bash.override { }; in { isNormalUser = true; shell = pkgs.bash; home = "/home/subspace"; packages = with pkgs; [ wishlist ]; }; # user for friends to ssh into friends = { isNormalUser = true; shell = pkgs.bash; home = "/home/friends"; # TEMP: remove and replace with home-manager packages = with pkgs; [ ]; }; }; }; virtualisation.docker.enable = true; home-manager = { users = { ae = import ../../homes/ae; subspace = import ../../homes/subspace; }; sharedModules = []; }; services = { # simple nginx instance to host static construction page # TODO: I want sshd and forgejo's ssh server to both be bound to port 22 # So change sshd to listen on a different address/port (ie 2222 or 127.0.0.3:22, etc) # and change forgejo to use 127.0.0.2:22 (use port 22, ONLY change loopback address) nginx = { enable = true; # in wake of CVE-2022-3602/CVE-2022-3786 package = pkgs.nginxStable.override {openssl = pkgs.libressl;}; #virtualHosts."imbored.dev".locations."/" = { virtualHosts = { "imbored.dev" = { # "http:imbored.dev" = { default = true; # serverName = "imbored.dev"; # listenAddresses = ["imbored.dev"]; enableACME = true; addSSL = true; # forceSSL = true; root = "/var/www/imbored"; #index = "index.html"; #root = pkgs.writeTextDir "index.html" '' # # # Give me your mittens! # # #''; }; # "ssh:imbored.dev" = { # serverName = "imbored.dev"; # listen = [{ # addr = "imbored.dev"; # port= 22; # }]; # locations."/".proxyPass = "ssh://127.0.0.1:2222"; # }; # Route "vault" subdomain to vaultwarden "vault.imbored.dev" = { enableACME = true; forceSSL = true; locations."/".proxyPass = "http://127.0.0.1:8222"; }; # Route "forge" subdomain to forgejo "forge.imbored.dev" = { # "https:forge.imbored.dev" = { #serverName = "forge.imbored.dev"; #listenAddresses = ["forge.imbored.dev"]; # NOTE: I think this is wrong enableACME = true; # TODO: maybe use `forgejo.settings.server.ENABLE_ACME` instead? forceSSL = true; extraConfig = '' client_max_body_size 512M; ''; locations."/".proxyPass = "http://127.0.0.1:3000"; }; # NOTE: would it work if I used "ssh://forge.imbored.dev" and "https://forge.imbored.dev" instead? # "ssh:forge.imbored.dev" = { # serverName = "forge.imbored.dev"; # listen = [{ # addr = "forge.imbored.dev"; # port = 22; # }]; # locations."/".proxyPass = "ssh://127.0.0.2:22"; # }; }; }; openssh = { enable = true; ports = [22]; settings = { PasswordAuthentication = true; PermitRootLogin = "no"; AllowUsers = ["ae" "subspace"]; # allow all users by default UseDns = true; X11Forwarding = false; }; }; vaultwarden = { enable = true; dbBackend = "sqlite"; # backupDir = "/var/backup/vaultwarden"; # disable with null # https://mynixos.com/nixpkgs/option/services.vaultwarden.config config = { # internal address and port to listen on ROCKET_ADDRESS = "127.0.0.1"; ROCKET_PORT = 8222; # hostname to listen for DOMAIN = "https://vault.imbored.dev"; SIGNUPS_ALLOWED = false; }; # https://mynixos.com/nixpkgs/option/services.vaultwarden.environmentFile environmentFile = "/var/lib/vaultwarden/vaultwarden.env"; }; # stalwart-mail = let # domain = "imbored.dev"; # in { # enable = false; # true; # # openFirewall = true; # im doing this manually rn # settings = { # certificate."${domain}" = { # cert = "file://${certs.${domain}.cert}"; # private-key = "file://${certs.${domain}.key}"; # }; # server = { # hostname = domain; # tls = { # certificate = "${domain}"; # enable = true; # implicit = false; # }; # listener = { # "smtp-submission" = { # bind = ["127.0.0.1:587"]; # protocol = "smtp"; # }; # "imap" = { # bind = ["127.0.0.1:143"]; # protocol = "imap"; # }; # }; # }; # session = { # rcpt.directory = "in-memory"; # auth = { # mechanisms = ["PLAIN"]; # directory = "in-memory"; # }; # }; # jmap.directory = "in-memory"; # queue.outbound.next-hop = ["local"]; # directory."in-memory" = { # type = "memory"; # users = [ # { # name = "me"; # secret = "foobar"; # email = ["me@${domain}"]; # } # { # name = "Emile"; # secret = "foobar"; # email = ["emile@${domain}"]; # } # ]; # }; # }; # }; # more options here: https://mynixos.com/nixpkgs/options/services.forgejo # TODO: set a favicon https://forgejo.org/docs/next/contributor/customization/#changing-the-logo # (might need me to override settings in the nixpkg) # TODO: create a custom theme for forgejo (modify the source files most likely) forgejo = { enable = true; # enable support for Git Large File Storage lfs.enable = true; database = { type = "sqlite3"; # postgres host = "127.0.0.1"; port = "3306"; # 5432 if postgres }; # settings are written directly to the `app.ini` config file # refer to: https://forgejo.org/docs/latest/admin/config-cheat-sheet/ settings = { server = { # ENABLE_ACME = true; # ACME_EMAIL = "eclarkboman@gmail.com"; # change this to "me@imbored.dev" DOMAIN = "forge.imbored.dev"; # should this be "imbored.dev"? ROOT_URL = "https://forge.imbored.dev"; # full public URL of the Forgejo server # address and port to listen on HTTP_ADDR = "127.0.0.1"; HTTP_PORT = 3000; PROTOCOL = "http"; # http internally, reverse proxy uses https externally START_SSH_SERVER = true; DISABLE_SSH = false; SSH_PORT = 2222; }; DEFAULT = { APP_NAME = "Emile's Forge"; APP_SLOGIN = "Cozy"; APP_DISPLAY_NAME_FORMAT = "{APP_NAME}: {APP_SLOGAN}"; }; repository = { DEFAULT_PRIVATE = "private"; # last, private, public DEFAULT_PUSH_CREATE_PRIVATE = true; MAX_CREATION_LIMIT = -1; }; "repository.upload" = { # max per-file size in MB FILE_MAX_SIZE = 50; # max number of files per upload MAX_FILES = 5; }; badges = let # flat, flat-square, plastic, for-the-badge, social style = "for-the-badge"; in { ENABLED = true; GENERATOR_URL_TEMPLATE = "https://img.shields.io/badge/{{.label}}-{{.text}}-{{.color}}?style=${style}"; }; ui = { DEFAULT_THEME = "forgejo-dark"; THEMES = "forgejo-auto,forgejo-light,forgejo-dark"; }; "ui.meta" = { AUTHOR = "Emile Clark-Boman - emileclarkb"; DESCRIPTION = "This is my personal self-hosted git forge, where I keep and maintain personal projects!"; KEYWORDS = "emileclarkb,git,forge,forgejo,self-hosted"; }; markdown = { ENABLE_HARD_LINE_BREAK_IN_COMMENTS = true; ENABLE_MATH = true; }; admin = { DEFAULT_EMAIL_NOTIFICATIONS = "enabled"; SEND_NOTIFICATION_EMAIL_ON_NEW_USER = true; }; security = { # Controls access to the installation page. # When set to “true”, the installation page is not accessible. #INSTALL_LOCK = false; PASSWORD_HASH_ALGO = "argon2"; # ARGON2 BEST ALGO FR!! MIN_PASSWORD_LENGTH = 12; PASSWORD_COMPLEXITY = "lower,upper,digit,spec"; PASSWORD_CHECK_PWN = true; }; service = { # toggle to create an admin user DISABLE_REGISTRATION = true; #DEFAULT_USER_IS_RESTRICTED = true; # Forbid login with third-party services (ie github) ALLOW_ONLY_INTERNAL_REGISTRATION = true; ENABLE_CAPTCHA = true; REQUIRE_CAPTCHA_FOR_LOGIN = true; REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA = true; LOGIN_REMEMBER_DAYS = 365; ENABLE_NOTIFY_MAIL = true; }; "service.explore" = { REQUIRE_SIGNIN_VIEW = false; DISABLE_USERS_PAGE = false; DISABLE_ORGANIZATIONS_PAGE = false; DISABLE_CODE_PAGE = false; }; cache = { ADAPTER = "twoqueue"; HOST = "{\"size\":100, \"recent_ratio\":0.25, \"ghost_ratio\":0.5}"; ITEM_TTL = "16h"; }; # TODO: fill this in once my mail server is configured # email.incoming = { ... }; # optional # TODO: fill this in once my mail server is configured mailer = { ENABLED = false; SMTP_ADDR = "mail.imbored.dev"; FROM = "noreply@imbored.dev"; USER = "noreply@imbored.dev"; }; log = { MODE = "file"; LEVEL = "Info"; # "Trace", "Debug", "Info", "Warn", "Error", "Critical" ENABLE_SSH_LOG = true; }; cron = { ENABLED = true; RUN_AT_START = false; }; other = { SHOW_FOOTER_VERSION = true; SHOW_FOOTER_TEMPLATE_LOAD_TIME = true; SHOW_FOOTER_POWERED_BY = true; ENABLE_SITEMAP = true; ENABLE_FEED = true; }; }; }; }; # accept Lets Encrypt's security policy (for nginx) security.acme = { acceptTerms = true; # TODO: change this to me@imbored.dev defaults.email = "eclarkboman@gmail.com"; }; environment.systemPackages = with pkgs; [ git vim helix ]; programs = { fish.enable = true; bash = { completion.enable = true; interactiveShellInit = '' if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]] then shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION="" exec ${pkgs.fish}/bin/fish $LOGIN_OPTION fi ''; }; }; #systemd.services.wishlist = { # description = "Single entrypoint for multiple SSH endpoints"; # wantedBy = ["multi-user.target"]; # # serviceConfig = { # DynamicUser = "yes"; # ExecStart = "${pkgs.wishlist}/bin/wishlist serve --config /home/$USER/.ssh/config"; # Restart = "always"; # RestartSec = "2s"; # }; #}; system.stateVersion = "24.11"; # DO NOT MODIFY }