From 42530f5cfcf9b672f8c76e9a199c999a87395396 Mon Sep 17 00:00:00 2001 From: Fabian Montero Date: Wed, 20 Nov 2024 17:52:37 -0600 Subject: [PATCH] unified all nixos configurations --- flake.nix | 2 +- home/default.nix | 50 -------- home/modules/baseline.nix | 16 +++ home/modules/default.nix | 1 + home/modules/neovim.nix | 8 +- home/modules/terminal/default.nix | 45 +++++++ home/{ => modules/terminal}/zshrc.nix | 0 .../fabian@posixlycorrect/default.nix | 1 + home/platforms/fabian@vps/cli.nix | 29 +++++ home/platforms/fabian@vps/default.nix | 33 ++++++ pkgs/default.nix | 8 +- .../factorio_blueprints/nauvis_science.txt | 1 + .../cdn/factorio_blueprints/red_circuits.txt | 1 + sys/platforms/vps/default.nix | 108 +++++++++++++++++ sys/platforms/vps/pki/fabian.ssh | 1 + sys/platforms/vps/pki/fabian_primary.gpg | 25 ++++ sys/platforms/vps/pki/fabian_yubikey.gpg | 19 +++ sys/platforms/vps/srv/authentik.nix | 110 ++++++++++++++++++ sys/platforms/vps/srv/bepasty.nix | 40 +++++++ sys/platforms/vps/srv/default.nix | 25 ++++ sys/platforms/vps/srv/firefly.nix | 33 ++++++ sys/platforms/vps/srv/forgejo.nix | 64 ++++++++++ sys/platforms/vps/srv/jellyfin.nix | 30 +++++ sys/platforms/vps/srv/jitsi.nix | 35 ++++++ sys/platforms/vps/srv/kuma.nix | 29 +++++ sys/platforms/vps/srv/matrix.nix | 58 +++++++++ sys/platforms/vps/srv/mediawiki.nix | 77 ++++++++++++ sys/platforms/vps/srv/msmtp.nix | 35 ++++++ sys/platforms/vps/srv/net.nix | 92 +++++++++++++++ sys/platforms/vps/srv/paperless.nix | 39 +++++++ sys/platforms/vps/srv/trilium.nix | 32 +++++ sys/platforms/vps/srv/vaultwarden.nix | 63 ++++++++++ 32 files changed, 1054 insertions(+), 56 deletions(-) create mode 100644 home/modules/baseline.nix rename home/{ => modules/terminal}/zshrc.nix (100%) create mode 100644 home/platforms/fabian@vps/cli.nix create mode 100644 home/platforms/fabian@vps/default.nix create mode 100644 sys/platforms/vps/cdn/factorio_blueprints/nauvis_science.txt create mode 100644 sys/platforms/vps/cdn/factorio_blueprints/red_circuits.txt create mode 100644 sys/platforms/vps/default.nix create mode 100644 sys/platforms/vps/pki/fabian.ssh create mode 100644 sys/platforms/vps/pki/fabian_primary.gpg create mode 100644 sys/platforms/vps/pki/fabian_yubikey.gpg create mode 100644 sys/platforms/vps/srv/authentik.nix create mode 100644 sys/platforms/vps/srv/bepasty.nix create mode 100644 sys/platforms/vps/srv/default.nix create mode 100644 sys/platforms/vps/srv/firefly.nix create mode 100644 sys/platforms/vps/srv/forgejo.nix create mode 100644 sys/platforms/vps/srv/jellyfin.nix create mode 100644 sys/platforms/vps/srv/jitsi.nix create mode 100644 sys/platforms/vps/srv/kuma.nix create mode 100644 sys/platforms/vps/srv/matrix.nix create mode 100644 sys/platforms/vps/srv/mediawiki.nix create mode 100644 sys/platforms/vps/srv/msmtp.nix create mode 100644 sys/platforms/vps/srv/net.nix create mode 100644 sys/platforms/vps/srv/paperless.nix create mode 100644 sys/platforms/vps/srv/trilium.nix create mode 100644 sys/platforms/vps/srv/vaultwarden.nix diff --git a/flake.nix b/flake.nix index 1e64c96..a01fb7f 100644 --- a/flake.nix +++ b/flake.nix @@ -68,7 +68,7 @@ inherit (pkgs.local.lib) importAll; - local = import ./pkgs; + local = final: prev: import ./pkgs {inherit final prev flakes;}; in with pkgs.lib; { formatter.${system} = pkgs.alejandra; diff --git a/home/default.nix b/home/default.nix index 0c7c6f3..5c7405a 100644 --- a/home/default.nix +++ b/home/default.nix @@ -1,4 +1,3 @@ -#TODO: keys will not be shared in all platforms { flakes, config, @@ -7,56 +6,7 @@ ... }: with lib; { - imports = [ ./modules ]; - - xdg.enable = true; - - programs = { - zsh = { - enable = true; - syntaxHighlighting.enable = true; - initExtra = import ./zshrc.nix pkgs; - }; - - git = { - enable = true; - userEmail = "fabian@posixlycorrect.com"; - userName = "Fabian Montero"; - signing = { - key = "7AA277E604A4173916BBB4E91FFAC35E1798174F"; - signByDefault = true; - }; - }; - gpg = { - enable = true; - settings = { - default-key = "7AA277E604A4173916BBB4E91FFAC35E1798174F"; - }; - }; - }; - - services.gpg-agent = { - enable = true; - enableZshIntegration = true; - pinentryPackage = pkgs.pinentry-emacs; - }; - - accounts.email.accounts = { - "fabian@posixlycorrect.com" = { - address = "fabian@posixlycorrect.com"; - userName = "fabianmontero@fastmail.com"; - realName = "fabian"; - primary = true; - flavor = "fastmail.com"; - - gpg = { - encryptByDefault = true; - signByDefault = true; - key = "7AA277E604A4173916BBB4E91FFAC35E1798174F"; - }; - }; - }; } diff --git a/home/modules/baseline.nix b/home/modules/baseline.nix new file mode 100644 index 0000000..cfe2fb4 --- /dev/null +++ b/home/modules/baseline.nix @@ -0,0 +1,16 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + cfg = config.local.baseline; +in { + options.local.baseline = { + enable = mkEnableOption "Basic settings"; + }; + config = mkIf cfg.enable { + xdg.enable = true; + }; +} diff --git a/home/modules/default.nix b/home/modules/default.nix index 89e2418..8b1c228 100644 --- a/home/modules/default.nix +++ b/home/modules/default.nix @@ -7,5 +7,6 @@ imports = [ ./terminal ./neovim.nix + ./baseline.nix ]; } diff --git a/home/modules/neovim.nix b/home/modules/neovim.nix index b026484..78dbc6f 100644 --- a/home/modules/neovim.nix +++ b/home/modules/neovim.nix @@ -3,7 +3,7 @@ lib, pkgs, ... -}: +}: with lib; let cfg = config.local.apps.neovim; in { @@ -19,10 +19,10 @@ in { extraConfig = '' set nobackup - set showmatch " show matching - set hlsearch " highlight search + set showmatch " show matching + set hlsearch " highlight search set incsearch " incremental search - set tabstop=4 " number of columns occupied by a tab + set tabstop=4 " number of columns occupied by a tab set softtabstop=4 " see multiple spaces as tabstops so does the right thing set shiftwidth=4 " width for autoindents set autoindent " indent a new line the same amount as the line just typed diff --git a/home/modules/terminal/default.nix b/home/modules/terminal/default.nix index 35df791..1914821 100644 --- a/home/modules/terminal/default.nix +++ b/home/modules/terminal/default.nix @@ -33,5 +33,50 @@ in { ''; }; }; + + programs.zsh = { + enable = true; + syntaxHighlighting.enable = true; + initExtra = import ./zshrc.nix pkgs; + }; + + programs.git = { + enable = true; + userEmail = "fabian@posixlycorrect.com"; + userName = "Fabian Montero"; + #signing = { + # key = "7AA277E604A4173916BBB4E91FFAC35E1798174F"; + # signByDefault = true; + #}; + }; + + programs.gpg = { + enable = true; + #settings = { + # default-key = "7AA277E604A4173916BBB4E91FFAC35E1798174F"; + #}; + }; + + services.gpg-agent = { + enable = true; + enableZshIntegration = true; + pinentryPackage = pkgs.pinentry-emacs; + }; + + accounts.email.accounts = { + "fabian@posixlycorrect.com" = { + address = "fabian@posixlycorrect.com"; + userName = "fabianmontero@fastmail.com"; + realName = "fabian"; + primary = true; + flavor = "fastmail.com"; + + gpg = { + encryptByDefault = true; + signByDefault = true; + key = "7AA277E604A4173916BBB4E91FFAC35E1798174F"; + }; + }; + }; }; } diff --git a/home/zshrc.nix b/home/modules/terminal/zshrc.nix similarity index 100% rename from home/zshrc.nix rename to home/modules/terminal/zshrc.nix diff --git a/home/platforms/fabian@posixlycorrect/default.nix b/home/platforms/fabian@posixlycorrect/default.nix index e37ad9f..0055a83 100644 --- a/home/platforms/fabian@posixlycorrect/default.nix +++ b/home/platforms/fabian@posixlycorrect/default.nix @@ -12,6 +12,7 @@ ./isolation.nix ]; + local.baseline = true; local.apps.terminal.enable = true; local.apps.neovim.enable = true; diff --git a/home/platforms/fabian@vps/cli.nix b/home/platforms/fabian@vps/cli.nix new file mode 100644 index 0000000..6476b39 --- /dev/null +++ b/home/platforms/fabian@vps/cli.nix @@ -0,0 +1,29 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + programs = { + zsh = { + enable = true; + syntaxHighlighting.enable = true; + }; + git = { + enable = true; + userEmail = "fabian@posixlycorrect.com"; + userName = "fabian"; + }; + neovim.enable = true; + }; + home.packages = with pkgs; [ + file + htop + killall + man-pages + man-pages-posix + tree + zip + unzip + ]; +} diff --git a/home/platforms/fabian@vps/default.nix b/home/platforms/fabian@vps/default.nix new file mode 100644 index 0000000..df58014 --- /dev/null +++ b/home/platforms/fabian@vps/default.nix @@ -0,0 +1,33 @@ +{ + config, + pkgs, + lib, + flakes, + ... +}: +with lib; { + imports = [ + ./cli.nix + ]; + + home = { + stateVersion = "24.05"; # No tocar esto + username = "fabian"; + homeDirectory = "/home/fabian"; + sessionVariables = { + "EDITOR" = "nvim"; + }; + }; + + xdg.enable = true; + + nix.registry = { + "system".to = { + type = "path"; + path = "/home/fabian/nix"; + }; + + "nixpkgs".flake = flakes.nixpkgs; + "unstable".flake = flakes.unstable; + }; +} diff --git a/pkgs/default.nix b/pkgs/default.nix index 95c3994..342a2a2 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,7 +1,13 @@ -final: prev: +{ + final, + prev, + flakes, +}: with prev.lib; let inherit (final) callPackage fetchpatch; in { + homepage = flakes.homepage.packages.${final.system}.default; + lib = callPackage ./lib {}; st = prev.st.override { diff --git a/sys/platforms/vps/cdn/factorio_blueprints/nauvis_science.txt b/sys/platforms/vps/cdn/factorio_blueprints/nauvis_science.txt new file mode 100644 index 0000000..2027858 --- /dev/null +++ b/sys/platforms/vps/cdn/factorio_blueprints/nauvis_science.txt @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/sys/platforms/vps/cdn/factorio_blueprints/red_circuits.txt b/sys/platforms/vps/cdn/factorio_blueprints/red_circuits.txt new file mode 100644 index 0000000..1e9e840 --- /dev/null +++ b/sys/platforms/vps/cdn/factorio_blueprints/red_circuits.txt @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/sys/platforms/vps/default.nix b/sys/platforms/vps/default.nix new file mode 100644 index 0000000..671056e --- /dev/null +++ b/sys/platforms/vps/default.nix @@ -0,0 +1,108 @@ +{ + config, + pkgs, + lib, + flakes, + ... +}: +with lib; { + imports = [ + flakes.vpsadminos.nixosConfigurations.container + flakes.home-manager.nixosModules.home-manager + flakes.impermanence.nixosModule + ./srv + ]; + + environment.systemPackages = with pkgs; [ + vim + git + ]; + + services.openssh = { + enable = true; + settings.PasswordAuthentication = false; + }; + + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + + extraSpecialArgs = {inherit flakes;}; + + users.fabian = { + imports = [ + flakes.impermanence.nixosModules.home-manager.impermanence + "${flakes.self}/home/platforms/fabian@vps" + "${flakes.self}/home" + ]; + }; + }; + + programs = { + zsh.enable = true; + fuse.userAllowOther = true; + }; + + networking.hostName = "vps"; + + nix = { + package = pkgs.nixFlakes; + + extraOptions = '' + experimental-features = nix-command flakes repl-flake + ''; + + # No me interesa el global registry + settings.flake-registry = ""; + }; + + users = { + users.fabian = { + isNormalUser = true; + uid = 1000; + group = "fabian"; + shell = pkgs.zsh; + extraGroups = ["users" "wheel" "networkmanager" "dialout" "libvirtd"]; + openssh.authorizedKeys.keyFiles = [pki/fabian.ssh]; + }; + groups.fabian.gid = 1000; + }; + + systemd.extraConfig = '' + DefaultTimeoutStartSec=900s + ''; + + security.dhparams = { + enable = true; + defaultBitSize = 4096; + }; + + fileSystems = { + "/mnt/export2008" = { + device = "172.16.129.19:/nas/5876"; + fsType = "nfs"; + options = ["nofail" "noatime"]; + }; + + "/mnt/export2011" = { + device = "172.16.129.151:/nas/5876/bepasty"; + fsType = "nfs"; + options = ["nofail" "noatime" "noexec"]; + }; + }; + + services.earlyoom = { + enable = mkDefault true; + enableNotifications = true; + }; + + # Coredumps son un riesgo de seguridad y puden usar mucho disco + systemd.coredump.extraConfig = '' + Storage=none + ProcessSizeMax=0 + ''; + + time.timeZone = "Europe/Amsterdam"; + + system.stateVersion = "24.05"; +} diff --git a/sys/platforms/vps/pki/fabian.ssh b/sys/platforms/vps/pki/fabian.ssh new file mode 100644 index 0000000..45b9932 --- /dev/null +++ b/sys/platforms/vps/pki/fabian.ssh @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHkK2Cg3dozG78AEA2OTzydezcKVnNTTj0MUJZcP/mrN fabian@posixlycorrect.com diff --git a/sys/platforms/vps/pki/fabian_primary.gpg b/sys/platforms/vps/pki/fabian_primary.gpg new file mode 100644 index 0000000..a84bcab --- /dev/null +++ b/sys/platforms/vps/pki/fabian_primary.gpg @@ -0,0 +1,25 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZHlROBYJKwYBBAHaRw8BAQdAhzA1JCghQ6KoHOuf6JPQhEmchHLVXFVye4I2 +pRUOUMO0KkZhYmlhbiBNb250ZXJvIDxmYWJpYW5AcG9zaXhseWNvcnJlY3QuY29t +PoiUBBMWCgA8FiEEeqJ35gSkFzkWu7TpH/rDXheYF08FAmR5UTgCGwMFCQlmAYAE +CwkIBwQVCgkIBRYCAwEAAh4FAheAAAoJEB/6w14XmBdPP2EA/i9ugFxpIFF6oOQs +clMfr+sNj6Il0OUTJK0dqpp4mGorAP0awa6nfhU8T1Ju7UWr6cfSmnL4bM6M/4Z3 +D+AF/L5PBokCMwQQAQoAHRYhBOd6gIv5qVXWaO7qZHP6nJy18CSbBQJkeVKDAAoJ +EHP6nJy18CSbzTkP/Reio0ObRrRW+QSw62ZXrUG0mFcNeeoM9amldCToFRyGnSDu +wtZ9nqwLiTJ01VPBOsEZLsl4VonO3rdadqnMTZ3XqKK9VHBl6UNot3DQ8INDAcko +GW1zvEdxNkpMxhtAja0JkcBdG7+zxc2aEGeKfEna2qDXA+xtYw5+pssOWYMip7hm +jQ2NzYMYav2KYRBC7eXTkAIIIJi/l9pR1IwHtY3a0gfbkQymgCyt5wVG6LneYFIR ++ycNVCObwyP8gFASdId0bWnA23rkilc9ZBOCps/cGfDLM+KQ+sLAWBFBQyQeEjcv +tU+pLXncAEvWy/SFmprVSLDQMMooFaEJMZChojGcCkwAPG1twsihqIA3E44Q3/+G +K0gZN57jGMnfvuQiuLuttOMdu27KwEu++t3YUt0P6S4kARpx51zZJ7A2Yj2u22aM +7EL8qq6KTNdNoS7FgwQkrWbokdDZIl0HV+5TeMQfylPqOPhuFK/1A9qztqknBPVY +QUx2t6FZUgH9sT7uD+5gXxyeqmEIFo2i6D8G/4TEPbKtWivJfeOqDEBn4QEY2nvE +zgJLLU5XCv9xPz5rizRCa+h+kg+i4mH6fLCBCCAPXsbAAo0gUlGJvX4slPh7uPOa +T2r7A/7uezResBzP/L/vostlmjO5c8cOl9Wc6D1kRZq17/AjMUgy6+KR3iVnuDgE +ZHlROBIKKwYBBAGXVQEFAQEHQPRbCS2p8xpt3fRxfyRnDOdH9pULY4NtGmZUS0ve +ZGkTAwEIB4h+BBgWCgAmFiEEeqJ35gSkFzkWu7TpH/rDXheYF08FAmR5UTgCGwwF +CQlmAYAACgkQH/rDXheYF0/65AD+LtDeedCYv9zs+1Ia3DvejVZM256WEH+dRH5h +Pm3RzQ8A/2+bXRnfsgGqacj/kKEL3spuos95ngRNRkrQ39nc1koP +=PAxr +-----END PGP PUBLIC KEY BLOCK----- diff --git a/sys/platforms/vps/pki/fabian_yubikey.gpg b/sys/platforms/vps/pki/fabian_yubikey.gpg new file mode 100644 index 0000000..15555b9 --- /dev/null +++ b/sys/platforms/vps/pki/fabian_yubikey.gpg @@ -0,0 +1,19 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZukhMBYJKwYBBAHaRw8BAQdAC/Gy2p7RPFw3k+ROFnKpJvCVqQb+BUYboE2u +CP1kz/C0KkZhYmlhbiBNb250ZXJvIDxmYWJpYW5AcG9zaXhseWNvcnJlY3QuY29t +PoiTBBMWCgA7FiEEcgbY7iR0898Y6odvDsFpH/jBqB8FAmbpITACGwMFCwkIBwIC +IgIGFQoJCAsCBBYCAwECHgcCF4AACgkQDsFpH/jBqB+oGwEAhmegCZJAt8Opv/9+ +HBbL51f2035qymHPgkV/SyFM1GEBAOVQY6A5U+NrLNiaQTN5Z7jcfQuBobzk4ksn +RzROhTcAiHUEEBYKAB0WIQR6onfmBKQXORa7tOkf+sNeF5gXTwUCZutnFQAKCRAf ++sNeF5gXT1juAQDsH/lDorfMdWxuP87eV9OP8jQvibuTuZ9n2jUllXsLcQEA5gDJ +05NW5Tw2g9mvlrocWr7N2/PC5UvFct4akwDXtA+4MwRm6SEwFgkrBgEEAdpHDwEB +B0AHSmncE+krtL9ZGe4eq865vjaLiUAVnZQaVObKm11CBYh4BBgWCgAgFiEEcgbY +7iR0898Y6odvDsFpH/jBqB8FAmbpITACGyAACgkQDsFpH/jBqB+hBwD/Y9vAcbPG +CTmZvtgYlZW5Oey5T3hHoANv1THOZwv9G58BALEBZRvDztmYPjRaMyAMonrpc2P0 +GPHYLcqCPVbjkaAKuDgEZukhMBIKKwYBBAGXVQEFAQEHQC2+QJcHEJjdZikBYeMj +ks53MjfeawAXU31KtAU60KACAwEIB4h4BBgWCgAgFiEEcgbY7iR0898Y6odvDsFp +H/jBqB8FAmbpITACGwwACgkQDsFpH/jBqB+0TwD+K4IcFstNGLrijlgH2zuQaI+p +8QT8AInjSpGfC4zcMlEBAIVYvdTYw4IXPSQOs0qPyR0nhfGIeoBMeWrAAfoxQ0oB +=wpc0 +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/sys/platforms/vps/srv/authentik.nix b/sys/platforms/vps/srv/authentik.nix new file mode 100644 index 0000000..8b68fe3 --- /dev/null +++ b/sys/platforms/vps/srv/authentik.nix @@ -0,0 +1,110 @@ +{ + lib, + pkgs, + flakes, + ... +}: +with lib; { + imports = [flakes.authentik-nix.nixosModules.default]; + + options = { + services.nginx.virtualHosts = mkOption { + type = with lib.types; + attrsOf ( + submodule + ( + {config, ...}: { + options = { + enableAuthentik = mkOption { + default = false; + type = bool; + }; + locations = mkOption { + type = attrsOf ( + submodule { + config = mkIf config.enableAuthentik { + extraConfig = '' + auth_request /outpost.goauthentik.io/auth/nginx; + error_page 401 = @goauthentik_proxy_signin; + auth_request_set $auth_cookie $upstream_http_set_cookie; + add_header Set-Cookie $auth_cookie; + + # translate headers from the outposts back to the actual upstream + auth_request_set $authentik_username $upstream_http_x_authentik_username; + auth_request_set $authentik_groups $upstream_http_x_authentik_groups; + auth_request_set $authentik_email $upstream_http_x_authentik_email; + auth_request_set $authentik_name $upstream_http_x_authentik_name; + auth_request_set $authentik_uid $upstream_http_x_authentik_uid; + + proxy_set_header X-authentik-username $authentik_username; + proxy_set_header X-authentik-groups $authentik_groups; + proxy_set_header X-authentik-email $authentik_email; + proxy_set_header X-authentik-name $authentik_name; + proxy_set_header X-authentik-uid $authentik_uid; + ''; + }; + } + ); + }; + }; + config = mkIf config.enableAuthentik { + extraConfig = '' + proxy_buffers 8 16k; + proxy_buffer_size 32k; + + location /outpost.goauthentik.io { + proxy_pass http://localhost:9000/outpost.goauthentik.io; + # ensure the host of this vserver matches your external URL you've configured + # in authentik + proxy_set_header Host $host; + proxy_redirect http://localhost:9000 https://auth.posixlycorrect.com; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + add_header Set-Cookie $auth_cookie; + auth_request_set $auth_cookie $upstream_http_set_cookie; + + # required for POST requests to work + proxy_pass_request_body off; + proxy_set_header Content-Length ""; + } + + location @goauthentik_proxy_signin { + internal; + add_header Set-Cookie $auth_cookie; + return 302 /outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri; + # For domain level, use the below error_page to redirect to your authentik server with the full redirect path + # return 302 https://authentik.company/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri; + } + ''; + }; + } + ) + ); + }; + }; + + config = { + services = { + authentik = { + enable = true; + environmentFile = "/var/trust/authentik/authentik-env"; + nginx = { + enable = true; + enableACME = true; + host = "auth.posixlycorrect.com"; + }; + settings = { + email = { + host = "smtp.fastmail.com"; + port = 587; + username = "fabianmontero@fastmail.com"; + use_tls = true; + use_ssl = false; + from = "auth@posixlycorrect.com"; + }; + disable_startup_analytics = true; + avatars = "initials"; + }; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/bepasty.nix b/sys/platforms/vps/srv/bepasty.nix new file mode 100644 index 0000000..964dbec --- /dev/null +++ b/sys/platforms/vps/srv/bepasty.nix @@ -0,0 +1,40 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + services = { + nginx = { + virtualHosts."send.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + locations."/" = { + proxyPass = "http://127.0.0.1:8989"; + }; + }; + }; + + bepasty = { + enable = true; + servers = { + "send" = { + bind = "127.0.0.1:8989"; + secretKeyFile = "/var/trust/bepasty/secretKeyFile"; + dataDir = "/mnt/export2011/data"; + defaultPermissions = "read,create,delete"; + extraConfig = '' + SITENAME = 'send.posixlycorrect.com' + MAX_ALLOWED_FILE_SIZE = 4 * 1000 * 1000 * 1000 + SESSION_COOKIE_SECURE = True + ASCIINEMA_THEME = 'asciinema' + ''; + }; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/default.nix b/sys/platforms/vps/srv/default.nix new file mode 100644 index 0000000..ead3824 --- /dev/null +++ b/sys/platforms/vps/srv/default.nix @@ -0,0 +1,25 @@ +{ + config, + pkgs, + lib, + flakes, + ... +}: +with lib; { + imports = [ + ./net.nix + ./mediawiki.nix + # ./jitsi.nix + # ./matrix.nix currently not being used + ./forgejo.nix + ./vaultwarden.nix + # ./bepasty.nix + # ./jellyfin.nix + ./msmtp.nix + ./kuma.nix + # ./authentik.nix consumes too much RAM and serves no purpose for now + ./paperless.nix + ./trilium.nix + ./firefly.nix + ]; +} diff --git a/sys/platforms/vps/srv/firefly.nix b/sys/platforms/vps/srv/firefly.nix new file mode 100644 index 0000000..e187e3c --- /dev/null +++ b/sys/platforms/vps/srv/firefly.nix @@ -0,0 +1,33 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + services = { + nginx = { + virtualHosts."firefly.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + }; + }; + + firefly-iii = { + enable = true; + user = "firefly-iii"; + dataDir = "/var/lib/firefly-iii"; + enableNginx = true; + virtualHost = "firefly.posixlycorrect.com"; + settings = { + SITE_OWNER = "fabian@posixlycorrect.com"; + DB_CONNECTION = "sqlite"; + APP_ENV = "local"; + APP_KEY_FILE = "/var/trust/firefly/key_file"; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/forgejo.nix b/sys/platforms/vps/srv/forgejo.nix new file mode 100644 index 0000000..25ff959 --- /dev/null +++ b/sys/platforms/vps/srv/forgejo.nix @@ -0,0 +1,64 @@ +{ + config, + lib, + ... +}: +with lib; { + config = { + environment.etc."fail2ban/filter.d/gitea.local".text = '' + [Definition] + failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from + ignoreregex = + ''; + + services = { + nginx = { + virtualHosts."git.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + locations."/".proxyPass = "http://localhost:9170"; + }; + }; + + fail2ban.jails.gitea.settings = { + filter = "gitea"; + logpath = "${config.services.gitea.stateDir}/log/gitea.log"; + maxretry = "10"; + findtime = "3600"; + bantime = "900"; + action = "iptables-allports"; + }; + + forgejo = { + enable = true; + lfs.enable = true; + useWizard = false; + settings = { + general.APP_NAME = "posixlycorrect"; + ui.DEFAULT_THEME = "forgejo-dark"; + server = { + DOMAIN = "git.posixlycorrect.com"; + ROOT_URL = "https://git.posixlycorrect.com"; + HTTP_PORT = 9170; + LANDING_PAGE = "explore"; + }; + + # You can temporarily allow registration to create an admin user. + service.DISABLE_REGISTRATION = true; + + # ver https://github.com/nektos/act + actions = { + ENABLED = false; + }; + mailer = { + ENABLED = false; + }; + }; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/jellyfin.nix b/sys/platforms/vps/srv/jellyfin.nix new file mode 100644 index 0000000..07c8896 --- /dev/null +++ b/sys/platforms/vps/srv/jellyfin.nix @@ -0,0 +1,30 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + services = { + nginx = { + virtualHosts."stream.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + locations."/" = { + proxyPass = "http://localhost:8096"; + }; + }; + }; + + jellyfin = { + enable = true; + user = "jellyfin"; + group = "jellyfin"; + dataDir = "/mnt/export2008/jellyfin/dataDir"; + cacheDir = "/mnt/export2008/jellyfin/cacheDir"; + }; + }; +} diff --git a/sys/platforms/vps/srv/jitsi.nix b/sys/platforms/vps/srv/jitsi.nix new file mode 100644 index 0000000..8fa1ccb --- /dev/null +++ b/sys/platforms/vps/srv/jitsi.nix @@ -0,0 +1,35 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + services = { + nginx = { + virtualHosts."meet.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + }; + }; + + jitsi-meet = { + enable = true; + hostName = "meet.posixlycorrect.com"; + nginx.enable = true; + config = { + enableWelcomePage = true; + prejoinPageEnabled = true; + defaultLang = "en"; + }; + interfaceConfig = { + SHOW_JITSI_WATERMARK = false; + SHOW_WATERMARK_FOR_GUESTS = false; + }; + }; + jitsi-videobridge.openFirewall = true; + }; +} diff --git a/sys/platforms/vps/srv/kuma.nix b/sys/platforms/vps/srv/kuma.nix new file mode 100644 index 0000000..e698c04 --- /dev/null +++ b/sys/platforms/vps/srv/kuma.nix @@ -0,0 +1,29 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + services = { + nginx = { + virtualHosts."status.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + locations."/" = { + proxyPass = "http://127.0.0.1:4456"; + }; + }; + }; + uptime-kuma = { + enable = true; + settings = { + HOST = "127.0.0.1"; + PORT = "4456"; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/matrix.nix b/sys/platforms/vps/srv/matrix.nix new file mode 100644 index 0000000..44644fd --- /dev/null +++ b/sys/platforms/vps/srv/matrix.nix @@ -0,0 +1,58 @@ +{ + lib, + pkgs, + config, + flakes, + ... +}: +with lib; let + subdomain = "matrix.posixlycorrect.com"; + baseUrl = "https://${subdomain}"; +in { + # ver https://nixos.org/manual/nixos/stable/#module-services-matrix + services = { + matrix-conduit = { + enable = true; + package = flakes.conduwuit.packages.${pkgs.system}.default; + settings.global = { + address = "::1"; + port = 6167; + allow_encryption = true; + allow_federation = true; + allow_registration = false; + database_backend = "rocksdb"; + server_name = "posixlycorrect.com"; + allow_check_for_updates = true; + new_user_displayname_suffix = ""; + }; + }; + + nginx.virtualHosts = let + clientConfig."m.homeserver".base_url = baseUrl; + serverConfig."m.server" = "${subdomain}:443"; + mkWellKnown = data: '' + default_type application/json; + add_header Access-Control-Allow-Origin *; + return 200 '${builtins.toJSON data}'; + ''; + in { + "posixlycorrect.com" = { + locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; + locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; + }; + "${subdomain}" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + locations."/".extraConfig = '' + return 403; + ''; + locations."/_matrix".proxyPass = "http://[::1]:6167"; + locations."/_synapse/client".proxyPass = "http://[::1]:6167"; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/mediawiki.nix b/sys/platforms/vps/srv/mediawiki.nix new file mode 100644 index 0000000..d806a18 --- /dev/null +++ b/sys/platforms/vps/srv/mediawiki.nix @@ -0,0 +1,77 @@ +{ + lib, + pkgs, + flakes, + ... +}: +with lib; { + services = { + nginx = { + virtualHosts."wiki.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + }; + }; + mediawiki = { + enable = true; + name = "posixlycorrect wiki"; + webserver = "nginx"; + nginx.hostName = "wiki.posixlycorrect.com"; + database.type = "postgres"; + + passwordFile = "/run/keys/mediawiki-password"; + + skins = { + citizen = "${flakes.mediawikiSkinCitizen}"; + }; + + extraConfig = '' + # Disable anonymous editing and account creation + $wgGroupPermissions['*']['edit'] = false; + $wgGroupPermissions['*']['createaccount'] = false; + + $wgDefaultSkin = 'citizen'; + $wgDefaultMobileSkin = 'citizen'; + $wgCitizenThemeDefault = 'dark'; + $wgCitizenShowPageTools = 'login'; + $wgLogos = [ + 'icon' => "https://posixlycorrect.com/favicon.png", + '1x' => "https://posixlycorrect.com/favicon.png", + '2x' => "https://posixlycorrect.com/favicon.png", + ]; + + $wgEnableEmail = false; #TODO: arreglar esto + $wgNoReplyAddress = 'mediawiki@posixlycorrect.com'; + $wgEmergencyContact = 'mediawiki@posixlycorrect.com'; + $wgPasswordSender = 'mediawiki@posixlycorrect.com'; + ''; + + extensions = { + # some extensions are included and can enabled by passing null + VisualEditor = null; + CategoryTree = null; + CiteThisPage = null; + Scribunto = null; + Cite = null; + CodeEditor = null; + Math = null; + MultimediaViewer = null; + PdfHandler = null; + Poem = null; + SecureLinkFixer = null; + WikiEditor = null; + ParserFunctions = null; + + TemplateStyles = pkgs.fetchzip { + url = "https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/TemplateStyles/+archive/refs/heads/wmf/1.42.0-wmf.9.tar.gz"; + sha256 = "sha256-+EOwkDU8L0qQ4Wo3WDqNug4Pyz/PUhOiHKmNcFJO4G0="; + stripRoot = false; + }; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/msmtp.nix b/sys/platforms/vps/srv/msmtp.nix new file mode 100644 index 0000000..89e9bae --- /dev/null +++ b/sys/platforms/vps/srv/msmtp.nix @@ -0,0 +1,35 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + users.groups = { + mailsenders = { + members = ["fabian" "mediawiki"]; + }; + }; + + # esto sirve para que PHP pueda accesar la clave smtp de fastmail + #systemd.services.phpfpm-mediawiki = { + # path = [ "/run/wrappers" ]; + # serviceConfig.ReadWritePaths = [ "/run/wrappers" "/var/trust/fastmail" ]; + #}; + + programs = { + msmtp = { + enable = true; + accounts = { + default = { + auth = true; + host = "smtp.fastmail.com"; + port = 587; + passwordeval = "cat /var/trust/fastmail/smtp_key"; + user = "fabianmontero@fastmail.com"; + tls = true; + tls_starttls = true; + }; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/net.nix b/sys/platforms/vps/srv/net.nix new file mode 100644 index 0000000..2a36fc2 --- /dev/null +++ b/sys/platforms/vps/srv/net.nix @@ -0,0 +1,92 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + networking = { + nftables.enable = true; + firewall = { + enable = true; + allowedTCPPorts = [80 443]; + }; + domain = "posixlycorrect.com"; + }; + + # ver https://nixos.org/manual/nixos/stable/index.html#module-security-acme-nginx + security.acme = { + acceptTerms = true; + defaults.email = "fabian@posixlycorrect.com"; + }; + + services = { + nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + logError = "/var/log/nginx/error.log"; + clientMaxBodySize = "99M"; + virtualHosts = { + "posixlycorrect.com" = { + forceSSL = true; + enableACME = true; + locations = { + "/".root = "${pkgs.local.homepage}"; + + "~ ^/pki(?:/(.*))?$" = { + # https://serverfault.com/a/476368 + alias = "${../pki}/$1"; + extraConfig = '' + autoindex on; + autoindex_exact_size on; + autoindex_localtime on; + autoindex_format html; + ''; + }; + + "~ ^/factorio_blueprints(?:/(.*))?$" = { + # https://serverfault.com/a/476368 + alias = "${../cdn/factorio_blueprints}/$1"; + extraConfig = '' + autoindex on; + autoindex_exact_size on; + autoindex_localtime on; + autoindex_format html; + ''; + }; + }; + }; + }; + }; + fail2ban = { + enable = true; + bantime = "10m"; + ignoreIP = ["37.205.12.34"]; # Never ban the server's own IP + bantime-increment = { + enable = true; + formula = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)"; + maxtime = "48h"; # Do not ban for more than 48h + rndtime = "10m"; + overalljails = true; # Calculate the bantime based on all the violations + }; + jails = { + # https://discourse.nixos.org/t/fail2ban-with-nginx-and-authelia/31419 + nginx-botsearch.settings = { + # Usar log en vez de journalctl + # TODO: Pasar todo a systemd? + backend = "pyinotify"; + logpath = "/var/log/nginx/*.log"; + journalmatch = ""; + }; + nginx-bad-request.settings = { + backend = "pyinotify"; + logpath = "/var/log/nginx/*.log"; + journalmatch = ""; + maxretry = 10; + }; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/paperless.nix b/sys/platforms/vps/srv/paperless.nix new file mode 100644 index 0000000..cb62bd9 --- /dev/null +++ b/sys/platforms/vps/srv/paperless.nix @@ -0,0 +1,39 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + services = { + nginx = { + virtualHosts."docs.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + locations."/" = { + proxyPass = "http://127.0.0.1:28981"; + }; + }; + }; + + paperless = { + enable = true; + user = "paperless"; + passwordFile = "/var/trust/paperless/passwordFile"; + openMPThreadingWorkaround = true; # see https://github.com/NixOS/nixpkgs/issues/240591 + address = "127.0.0.1"; + port = 28981; + settings = { + PAPERLESS_URL = "docs.posixlycorrect.com"; + PAPERLESS_OCR_LANGUAGE = "eng+spa"; + PAPERLESS_APP_TITLE = "posixlycorrect"; + PAPERLESS_OCR_USER_ARGS = { + "invalidate_digital_signatures" = true; + }; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/trilium.nix b/sys/platforms/vps/srv/trilium.nix new file mode 100644 index 0000000..e129eba --- /dev/null +++ b/sys/platforms/vps/srv/trilium.nix @@ -0,0 +1,32 @@ +{ + lib, + pkgs, + ... +}: +with lib; { + services = { + nginx = { + virtualHosts."notes.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + }; + }; + + trilium-server = { + enable = true; + host = "127.0.0.1"; + port = 8458; + noAuthentication = false; + instanceName = "posixlycorrect"; + dataDir = "/var/lib/trilium"; + nginx = { + enable = true; + hostName = "notes.posixlycorrect.com"; + }; + }; + }; +} diff --git a/sys/platforms/vps/srv/vaultwarden.nix b/sys/platforms/vps/srv/vaultwarden.nix new file mode 100644 index 0000000..2b8dc91 --- /dev/null +++ b/sys/platforms/vps/srv/vaultwarden.nix @@ -0,0 +1,63 @@ +{ + config, + lib, + ... +}: +with lib; { + services = { + nginx = { + virtualHosts."vault.posixlycorrect.com" = { + enableACME = true; + forceSSL = true; + extraConfig = '' + proxy_headers_hash_max_size 512; + proxy_headers_hash_bucket_size 128; + ''; + locations."/".proxyPass = "http://127.0.0.1:${toString config.services.vaultwarden.config.ROCKET_PORT}"; + }; + }; + + #fail2ban.jails.gitea.settings = { }; + + postgresql = { + ensureDatabases = ["vaultwarden"]; + ensureUsers = [ + { + name = "vaultwarden"; + ensureDBOwnership = true; + } + ]; + }; + + vaultwarden = { + enable = true; + dbBackend = "postgresql"; + environmentFile = "/var/trust/vaultwarden/smtp_key"; + config = { + DOMAIN = "https://vault.posixlycorrect.com"; + SIGNUPS_ALLOWED = false; + + ROCKET_ADDRESS = "127.0.0.1"; + ROCKET_PORT = 8222; + + ROCKET_LOG = "critical"; + + # Using FASTMAIL mail server + # If you use an external mail server, follow: + # https://github.com/dani-garcia/vaultwarden/wiki/SMTP-configuration + SMTP_HOST = "smtp.fastmail.com"; + SMTP_PORT = 587; + SMTP_SECURITY = "starttls"; + + SMTP_FROM = "vault@posixlycorrect.com"; + SMTP_FROM_NAME = "posixlycorrect vaultwarden server"; + + SMTP_AUTH_MECHANISM = "PLAIN"; + + DATABASE_URL = "postgresql:///vaultwarden"; + }; + }; + + bitwarden-directory-connector-cli.domain = "https://vault.posixlycorrect.com"; + }; +}