helix zone
This commit is contained in:
		
							parent
							
								
									ea1cea6b13
								
							
						
					
					
						commit
						ae93d24e7a
					
				
							
								
								
									
										60
									
								
								profiles/helix-zone/configuration.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								profiles/helix-zone/configuration.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| { config, pkgs, ... }: | ||||
| { | ||||
|   imports = | ||||
|     [ # Include the results of the hardware scan. | ||||
|       ./hardware-configuration.nix | ||||
|       ./wireguard.nix | ||||
|       ./matrix.nix | ||||
|       ./monitoring.nix | ||||
|       ./rss-bridge.nix | ||||
|       ./gitea.nix | ||||
|       # ./dns.nix | ||||
|       "${builtins.fetchTarball "https://github.com/ryantm/agenix/archive/main.tar.gz"}/modules/age.nix" | ||||
|     ]; | ||||
| 
 | ||||
|   # Use the GRUB 2 boot loader. | ||||
|   boot.loader.grub.enable = true; | ||||
|   boot.loader.grub.version = 2; | ||||
|   boot.loader.grub.device = "/dev/vda"; # or "nodev" for efi only | ||||
| 
 | ||||
|   networking.hostName = "helix"; # Define your hostname. | ||||
| 
 | ||||
|   networking.useDHCP = false; | ||||
|   networking.interfaces.ens3.useDHCP = true; | ||||
| 
 | ||||
|   # Configure network proxy if necessary | ||||
|   # networking.proxy.default = "http://user:password@proxy:port/"; | ||||
|   # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; | ||||
| 
 | ||||
|   # Enable the OpenSSH daemon. | ||||
|   services.openssh.enable = true; | ||||
|   services.openssh.passwordAuthentication = false; | ||||
|   services.openssh.permitRootLogin = "no"; | ||||
| 
 | ||||
|   # Open ports in the firewall. | ||||
|   # networking.firewall.allowedTCPPorts = [ ... ]; | ||||
|   # networking.firewall.allowedUDPPorts = [ ... ]; | ||||
|   # Or disable the firewall altogether. | ||||
|   # networking.firewall.enable = false; | ||||
| 
 | ||||
|   # Include agenix | ||||
|   #environment.systemPackages = [ agenix.defaultPackage.x86_64-linux ]; | ||||
| 
 | ||||
|   # Define a user account. Don't forget to set a password with ‘passwd’. | ||||
|   users.users.anish = { | ||||
|     isNormalUser = true; | ||||
|     extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user | ||||
|     openssh.authorizedKeys.keys = [ | ||||
| 	"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDM0Zvei46x/yZl/IeBCq6+IYQQ0avulzVyBysF9cPigZMCybWRV7IEU+E3k9t6JrbdbdGfJkcZIWmsWDdKS8W8mBnZpVoT0ffLynu8JQ/TKdGm4Qv6bgUeKNrGsNv0ZPs2CDaGSLj0oJfRF7Ko10tcLP0vW+yujrh+y6TH/vVzJioaV4TGvtCUpn+wEQah9ROwPQLUUofsSWdnRsDJ/gp37zXWs4l5wyjSKtP3O9RZUP7kBekbSqEgSXiTk0oUQSVqIWl9NDiP6onk/gSOjXsR/JPqsSN/XI/c/yj6gyY0f51Ru2D7iBxuMJIJcWV+rU6coIj+ULcQWLzt/7TI8jq5AOOzI/ll4zbL24Eo84Rz+TP9tvMMhDZ0VaMN22AJ8qQEjc5P09tWKsX7Jg39XelyV1jHXncE4yvIE9F4RSCHzWCeKeXakizQNuzSaxTxIExRFYHjNW5bR6+3MTGwVrEIXU+qML+0yFTR86MT+tdY5AreAJQLwbog79O1NupeXJE= anish@curve"   | ||||
| 	"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCeWQsf9rbE+KBrWLkLkg1PMKx0jPfDP8xyv+XtddIQzAskRTN+JSSQp1GpoRgfQij7bx6f6DfjkwSQK5NWDQNQ+klGhcdEwEdptWUzpRAvKHMImjyIwFHmRKKEgcfH8+DSHVM93nRSQKrLezX4PzPkHF9f3TLxFdGeQDeY0J2oP2Oa97hRtuTJZW9BwUojyvDYUbg7F3fxf+pdFCvIAFaayiLkhOYdTXnjLt1Ks6NOhSzM78ZibHv4pFYI9r6dhflkFP/SzyLeSSm1aVAtxqE7vF5HnnORAg0byDsiOv/9RXxiDx7gkAAw3xENDSpp9TRj54M7iz1OSsRMhmD6orHjZFIRejlE4DIn+PBPm3PH+U5ILKTogE6n5MfPT28V0QdtHuqq3b5tSWiDcFpnjxbIUmEIo5hLzMR0tXZoNLQhBCSNfxjE8CYzpk7mHbvhSs2GPfG+NI1vvldbw2EF8beJFQHNYTqJw8y7p8RXpCwZqqpSitJX6v9DiYdLVG1hWvE= nix-on-droid@localhost" | ||||
| 	 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKN8/SH55DBiwVoSnTU8k2Pen+wmovL9QaMyehxGEsJJv/8fzwsswGalD4C/4O51LOvdu4UKkZW5hG02uVSK+58p3UV3pOPyoqsu/aDeIsWsqmTeTzUrBIWOlNzcDKnohLz2oGC5YO+wyTJ9Iteq6aGJDjErsW7sG3h5lXCs551EmJNNGhtBQaaoytMNnWqSdlVjDNCijurH7WUpp40U/RjEp532l4rX6eIIj3jBKEFbhZkFSSjqbj4xM4SyFt+Jmigb1RMjsQjmpfY1vDtM84RcYfpTUte/T5w2dkD5H6kccmWnwKSJpm9wXfx4E7lR9APdUGnau2U1+XxiD3ytGl anish@box" ]; | ||||
|   }; | ||||
| 
 | ||||
|   # This value determines the NixOS release with which your system is to be | ||||
|   # compatible, in order to avoid breaking some software such as database | ||||
|   # servers. You should change this only after NixOS release notes say you | ||||
|   # should. | ||||
|   system.stateVersion = "19.09"; # Did you read the comment? | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										54
									
								
								profiles/helix-zone/dns.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								profiles/helix-zone/dns.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| { pkgs, ... }: | ||||
| 
 | ||||
| let | ||||
|   adblockLocalZones = pkgs.stdenv.mkDerivation { | ||||
|     name = "unbound-zones-adblock"; | ||||
| 
 | ||||
|     src = (pkgs.fetchFromGitHub { | ||||
|       owner = "StevenBlack"; | ||||
|       repo = "hosts"; | ||||
|       rev = "3.0.0"; | ||||
|       sha256 = "01g6pc9s1ah2w1cbf6bvi424762hkbpbgja9585a0w99cq0n6bxv"; | ||||
|     } + "/hosts"); | ||||
| 
 | ||||
|     phases = [ "installPhase" ]; | ||||
| 
 | ||||
|     installPhase = '' | ||||
|       ${pkgs.gawk}/bin/awk '{sub(/\r$/,"")} {sub(/^127\.0\.0\.1/,"0.0.0.0")} BEGIN { OFS = "" } NF == 2 && $1 == "0.0.0.0" { print "local-zone: \"", $2, "\" static"}' $src | tr '[:upper:]' '[:lower:]' | sort -u >  $out | ||||
|     ''; | ||||
|   }; | ||||
| 
 | ||||
| in { | ||||
|   networking.firewall.allowedTCPPorts = [ 53 853 5353 ]; | ||||
|   networking.firewall.allowedUDPPorts = [ 53 853 5353 ]; | ||||
|   networking.extraHosts = '' 127.0.0.1 helix.domain ''; | ||||
| 	  # These are causing errors, goes in the server file | ||||
| 	  # local-data = "mossnet.lan. 10800 IN A 10.0.69.4"; | ||||
|   services.unbound = { | ||||
|     enable = true; | ||||
|     settings = { | ||||
| 	  server = { | ||||
| 	    interface = [ "0.0.0.0" ]; | ||||
| 	    tls-upstream = true; | ||||
|             tls-cert-bundle = "/etc/ssl/certs/ca-certificates.crt"; | ||||
| 	    include = "${adblockLocalZones}"; | ||||
| 	    access-control = "0.0.0.0/0 allow"; | ||||
| 	    verbosity = 2; | ||||
| 	    do-tcp = true; | ||||
| 	    do-ip4 = true; | ||||
| 	    prefetch = true; | ||||
| 	    prefetch-key = true; | ||||
| 	    rrset-roundrobin = true; | ||||
| 	    qname-minimisation-strict = true; | ||||
| 	    hide-identity = true; | ||||
| 	    hide-version = true; | ||||
| 	    local-zone = "mossnet.lan. static"; | ||||
| 	  }; | ||||
| 	  forward-zone = [{ | ||||
|             name = "."; | ||||
|             forward-addr = [  "45.90.28.77#c46fd3.dns1.nextdns.io" "2a07:a8c0::#c46fd3.dns1.nextdns.io" "45.90.30.77#c46fd3.dns2.nextdns.io" "2a07:a8c1::#c46fd3.dns2.nextdns.io" ]; | ||||
| 	  }]; | ||||
| 	  remote-control.control-enable = true; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										53
									
								
								profiles/helix-zone/gitea.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								profiles/helix-zone/gitea.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | |||
| { config, lib, pkgs, ... }: | ||||
| 
 | ||||
| { | ||||
|   services.gitea = { | ||||
|     enable = true; | ||||
|     appName = "Sealight Git Forge"; | ||||
|     domain = "git.sealight.xyz"; | ||||
|     rootUrl = "https://git.sealight.xyz"; | ||||
|     httpPort = 3001; | ||||
|     database = { | ||||
|       type = "postgres"; | ||||
|       # passwordFile = "/run/secrets/gitea-dbpass"; # supplied by agenix | ||||
|       password = "somethingunknowablesorry"; | ||||
|     }; | ||||
|     settings = { | ||||
|       metrics = { | ||||
|         ENABLED = true; | ||||
|       }; | ||||
|       repository = { | ||||
| 	DEFAULT_BRANCH = "main"; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
| 
 | ||||
|   services.postgresql = { | ||||
|     enable = true;                # Ensure postgresql is enabled | ||||
|     authentication = '' | ||||
|       local gitea all ident map=gitea-users | ||||
|     ''; | ||||
|     identMap =                    # Map the gitea user to postgresql | ||||
|       '' | ||||
|         gitea-users gitea gitea | ||||
|       ''; | ||||
|     # ensureDatabases = [ "gitea" ]; | ||||
|     # ensureUsers = [  | ||||
|     #   { name = "gitea"; ensurePermissions."DATABASE gitea" = "ALLPRIVLEGES"; } | ||||
|     # ]; | ||||
|   }; | ||||
| 
 | ||||
|   services.nginx = { | ||||
|    enable = true;                                          # Enable Nginx | ||||
|    recommendedGzipSettings = true; | ||||
|    recommendedOptimisation = true; | ||||
|    recommendedProxySettings = true; | ||||
|    recommendedTlsSettings = true; | ||||
|    virtualHosts."git.sealight.xyz" = {                  # Gitea hostname | ||||
|      enableACME = true;                                    # Use ACME certs | ||||
|      forceSSL = true;                                      # Force SSL | ||||
|      locations."/".proxyPass = "http://localhost:3001/";   # Proxy Gitea | ||||
|    }; | ||||
|  }; | ||||
| } | ||||
							
								
								
									
										24
									
								
								profiles/helix-zone/hardware-configuration.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								profiles/helix-zone/hardware-configuration.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| # Do not modify this file!  It was generated by ‘nixos-generate-config’ | ||||
| # and may be overwritten by future invocations.  Please make changes | ||||
| # to /etc/nixos/configuration.nix instead. | ||||
| { config, lib, pkgs, ... }: | ||||
| 
 | ||||
| { | ||||
|   imports = | ||||
|     [ <nixpkgs/nixos/modules/profiles/qemu-guest.nix> | ||||
|     ]; | ||||
| 
 | ||||
|   boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ]; | ||||
|   boot.initrd.kernelModules = [ ]; | ||||
|   boot.kernelModules = [ ]; | ||||
|   boot.extraModulePackages = [ ]; | ||||
| 
 | ||||
|   fileSystems."/" = | ||||
|     { device = "/dev/disk/by-uuid/3b8b2c4b-835e-4822-8ac8-0effdc8270d6"; | ||||
|       fsType = "btrfs"; | ||||
|     }; | ||||
| 
 | ||||
|   swapDevices = [ ]; | ||||
| 
 | ||||
|   nix.maxJobs = lib.mkDefault 1; | ||||
| } | ||||
							
								
								
									
										82
									
								
								profiles/helix-zone/knot.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								profiles/helix-zone/knot.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,82 @@ | |||
| # SPDX-License-Identifier: Apache-2.0 | ||||
| { config, pkgs, ... }: | ||||
| let | ||||
|   # https://github.com/StevenBlack/hosts/issues/451 | ||||
|   # https://github.com/ScriptTiger/Hosts-Conversions | ||||
|   # https://github.com/ScriptTiger/scripttiger.github.io | ||||
|   # https://scripttiger.github.io/alts/ | ||||
|   adblockLocalZones = pkgs.stdenv.mkDerivation { | ||||
|     name = "adblock-rpz"; | ||||
|     src = (pkgs.fetchFromGitHub { | ||||
|         owner = "ScriptTiger"; | ||||
|         repo = "scripttiger.github.io"; | ||||
|         # nix-prefetch-github ScriptTiger scripttiger.github.io | ||||
|         rev = "04402a6726f97c5f0d30436a70ac1344dccb7cf1"; | ||||
|         sha256 = "iSTR7j7QEr5xYtImyntDlVLbnN2ipcLcTRr4sfdx078="; | ||||
|       } + "/alts/rpz/blacklist.txt"); | ||||
|     phases = [ "installPhase" ]; | ||||
|     installPhase = "install -m 444 -D $src $out"; | ||||
|   }; | ||||
|   domain = "sealight.xyz"; | ||||
|   certdir = config.security.acme.certs.${domain}.directory; | ||||
| in { | ||||
|   networking.firewall.allowedTCPPorts = [ 853 ]; | ||||
|   networking.firewall.allowedUDPPorts = [ 853 ]; | ||||
| 
 | ||||
|   # for acme certs, TODO: make a proper group | ||||
|   users.users.knot-resolver.extraGroups = [ "nginx" ]; | ||||
| 
 | ||||
|   # https://github.com/NixOS/nixpkgs/issues/81109 | ||||
|   nixpkgs.config.packageOverrides = pkgs: rec { | ||||
|     knot-resolver = pkgs.knot-resolver.override { extraFeatures = true; }; | ||||
|   }; | ||||
|   services.kresd = { | ||||
|     enable = true; | ||||
|     # Plain DNS only from localhost. | ||||
|     # You might want to add a LAN or VPN subnet, depending on deployment. | ||||
|     #listenPlain = [ "127.0.0.1:53" "[::1]:53" ]; | ||||
|     listenTLS = [ "853" ]; | ||||
|     #listenDoH = [ "" "[::]:443" ]; | ||||
|     instances = 1; | ||||
|     # TODO: chain.pem for stapling: https://gitlab.nic.cz/knot/knot-resolver/-/issues/517 | ||||
|       #policy.add( | ||||
|       #    policy.rpz( | ||||
|       #        policy.DENY_MSG('domain blocked by your resolver operator'), | ||||
|       #        '${adblockLocalZones}', | ||||
|       #        false)) | ||||
|     extraConfig = '' | ||||
|       modules.load('predict') | ||||
|       modules = { 'hints > iterate' } | ||||
|       policy.add( | ||||
|           policy.all( | ||||
|               policy.TLS_FORWARD({ | ||||
|                   {'45.90.30.0', hostname='87b4e9.dns2.nextdns.io'}, | ||||
| 		  {'45.90.28.0', hostname='87b4e9.dns1.nextdns.io'} | ||||
|                   }))) | ||||
|       policy.add(policy.suffix(policy.FORWARD({'10.0.69.4', '172.16.11.240'}), {todname('mossnet.lan')})) | ||||
| 
 | ||||
|       net.tls("${certdir}/fullchain.pem", "${certdir}/key.pem") | ||||
| 
 | ||||
|       -- refresh certs when ACME updates them | ||||
|       -- TODO: could probably do with systemd and a control socket? | ||||
|       -- TODO: may fail on first boot if ACME isn't fast, add a systemd dep | ||||
|       local notify = require('cqueues.notify') | ||||
|       local watcher = notify.opendir('${certdir}') | ||||
|       watcher:add('fullchain.pem') | ||||
| 
 | ||||
|       worker.coroutine(function () | ||||
|         for flags, name in watcher:changes() do | ||||
|           for flag in notify.flags(flags) do | ||||
|             print('file watcher:', name, notify[flag]) | ||||
|           end | ||||
|           if name == 'fullchain.pem' then | ||||
|             net.tls("${certdir}/fullchain.pem", "${certdir}/key.pem") | ||||
|           end | ||||
|         end | ||||
|       end) | ||||
| 
 | ||||
|       -- Below we create a tmpfs FS for the cache -- use almost all of it: | ||||
|       cache.size = cache.fssize() - 1*MB | ||||
|     ''; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										153
									
								
								profiles/helix-zone/matrix-slack.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								profiles/helix-zone/matrix-slack.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,153 @@ | |||
| { config, pkgs, lib, ... }: | ||||
| 
 | ||||
| with lib; | ||||
| 
 | ||||
| let | ||||
|   dataDir = "/var/lib/matrix-appservice-slack"; | ||||
|   registrationFile = "${dataDir}/slack-registration.yaml"; | ||||
|   #appDir = "${pkgs.matrix-appservice-slack}/${pkgs.matrix-appservice-slack.passthru.nodeAppDir}"; | ||||
|   cfg = config.services.matrix-appservice-slack; | ||||
|   # TODO: switch to configGen.json once RFC42 is implemented | ||||
|   settingsFile = pkgs.writeText "matrix-appservice-slack-settings.json" (builtins.toJSON cfg.settings); | ||||
| 
 | ||||
| in { | ||||
|   options = { | ||||
|     services.matrix-appservice-slack = { | ||||
|       enable = mkEnableOption "a bridge between Matrix and Slack"; | ||||
| 
 | ||||
|       settings = mkOption rec { | ||||
|         # TODO: switch to types.config.json as prescribed by RFC42 once it's implemented | ||||
|         type = types.attrs; | ||||
|         apply = recursiveUpdate default; | ||||
|         default = { | ||||
|           # empty values necessary for registration file generation | ||||
|           # actual values defined in environmentFile | ||||
|           auth = { | ||||
|             clientID = ""; | ||||
|             botToken = ""; | ||||
|           }; | ||||
|         }; | ||||
|         example = literalExample '' | ||||
|           { | ||||
|             bridge = { | ||||
|               domain = "public-domain.tld"; | ||||
|               homeserverUrl = "http://public-domain.tld:8008"; | ||||
|             }; | ||||
|           } | ||||
|         ''; | ||||
|         description = '' | ||||
|           <filename>config.yaml</filename> configuration as a Nix attribute set. | ||||
|           </para> | ||||
| 
 | ||||
|           <para> | ||||
|           Configuration options should match those described in | ||||
|           <link xlink:href="https://github.com/Half-Shot/matrix-appservice-discord/blob/master/config/config.sample.yaml"> | ||||
|           config.sample.yaml</link>. | ||||
|           </para> | ||||
| 
 | ||||
|           <para> | ||||
|           <option>config.bridge.domain</option> and <option>config.bridge.homeserverUrl</option> | ||||
|           should be set to match the public host name of the Matrix homeserver for webhooks and avatars to work. | ||||
|           </para> | ||||
| 
 | ||||
|           <para> | ||||
|           Secret tokens should be specified using <option>environmentFile</option> | ||||
|           instead of this world-readable attribute set. | ||||
|         ''; | ||||
|       }; | ||||
| 
 | ||||
|       environmentFile = mkOption { | ||||
|         type = types.nullOr types.path; | ||||
|         default = null; | ||||
|         description = '' | ||||
|           File containing environment variables to be passed to the matrix-appservice-discord service, | ||||
|           in which secret tokens can be specified securely by defining values for | ||||
|           <literal>APPSERVICE_SLACK_AUTH_CLIENT_I_D</literal> and | ||||
|           <literal>APPSERVICE_SLACK_AUTH_BOT_TOKEN</literal>. | ||||
|         ''; | ||||
|       }; | ||||
| 
 | ||||
|       url = mkOption { | ||||
|         type = types.str; | ||||
|         default = "http://localhost:${toString cfg.port}"; | ||||
|         description = '' | ||||
|           The URL where the application service is listening for HS requests. | ||||
|         ''; | ||||
|       }; | ||||
| 
 | ||||
|       port = mkOption { | ||||
|         type = types.port; | ||||
|         default = 9898; # from https://github.com/matrix-org/matrix-appservice-slack/blob/develop/config/config.sample.yaml#L70 | ||||
|         description = '' | ||||
|           Port number on which the bridge should listen for internal communication with the Matrix homeserver. | ||||
|         ''; | ||||
|       }; | ||||
| 
 | ||||
|       localpart = mkOption { | ||||
|         type = with types; nullOr str; | ||||
|         default = null; | ||||
|         description = '' | ||||
|           The user_id localpart to assign to the AS. | ||||
|         ''; | ||||
|       }; | ||||
| 
 | ||||
|       serviceDependencies = mkOption { | ||||
|         type = with types; listOf str; | ||||
|         default = optional config.services.matrix-synapse.enable "matrix-synapse.service"; | ||||
|         description = '' | ||||
|           List of Systemd services to require and wait for when starting the application service, | ||||
|           such as the Matrix homeserver if it's running on the same host. | ||||
|         ''; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = mkIf cfg.enable { | ||||
|     systemd.services.matrix-appservice-slack = { | ||||
|       description = "A bridge between Matrix and Slack."; | ||||
| 
 | ||||
|       wantedBy = [ "multi-user.target" ]; | ||||
|       wants = [ "network-online.target" ] ++ cfg.serviceDependencies; | ||||
|       after = [ "network-online.target" ] ++ cfg.serviceDependencies; | ||||
| 
 | ||||
|       preStart = '' | ||||
|         if [ ! -f '${registrationFile}' ]; then | ||||
|           ${pkgs.matrix-appservice-slack}/bin/matrix-appservice-slack \ | ||||
|             --generate-registration \ | ||||
|             --url=${escapeShellArg cfg.url} \ | ||||
|             ${optionalString (cfg.localpart != null) "--localpart=${escapeShellArg cfg.localpart}"} \ | ||||
|             --config='${settingsFile}' \ | ||||
|             --file='${registrationFile}' | ||||
|         fi | ||||
|       ''; | ||||
| 
 | ||||
|       serviceConfig = { | ||||
|         Type = "simple"; | ||||
|         Restart = "always"; | ||||
| 
 | ||||
|         ProtectSystem = "strict"; | ||||
|         ProtectHome = true; | ||||
|         ProtectKernelTunables = true; | ||||
|         ProtectKernelModules = true; | ||||
|         ProtectControlGroups = true; | ||||
| 
 | ||||
|         DynamicUser = true; | ||||
|         PrivateTmp = true; | ||||
|         #WorkingDirectory = appDir; | ||||
|         StateDirectory = baseNameOf dataDir; | ||||
|         UMask = 0027; | ||||
|         EnvironmentFile = cfg.environmentFile; | ||||
| 
 | ||||
|         ExecStart = '' | ||||
|           ${pkgs.matrix-appservice-slack}/bin/matrix-appservice-slack \ | ||||
|             --file='${registrationFile}' \ | ||||
|             --config='${settingsFile}' \ | ||||
|             --port='${toString cfg.port}' | ||||
|         ''; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   meta.maintainers = with maintainers; [ chickensoupandrice ]; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										375
									
								
								profiles/helix-zone/matrix.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										375
									
								
								profiles/helix-zone/matrix.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,375 @@ | |||
| { config, lib, pkgs, ... }: | ||||
| 
 | ||||
| { | ||||
|   imports = [  | ||||
| 	#./mod-mx-puppet-slack.nix  | ||||
| 	./mautrix-whatsapp.nix  | ||||
| 	./mod-heisenbridge.nix | ||||
|   ]; | ||||
|   security.acme.email = "anish+acme@lakhwara.com"; | ||||
|   security.acme.acceptTerms = true; | ||||
|   services.matrix-synapse = { | ||||
|     enable = true; | ||||
|     app_service_config_files = [ | ||||
|     #  # The registration file is automatically generated after starting the appservice for the first time. | ||||
|     #  # cp /var/lib/matrix-appservice-discord/discord-registration.yaml /var/lib/matrix-synapse/ | ||||
|     #  # chown matrix-synapse:matrix-synapse /var/lib/matrix-synapse/discord-registration.yaml | ||||
|        "/var/lib/matrix-synapse/discord-registration.yaml" | ||||
|        "/var/lib/matrix-synapse/telegram-registration.yaml" | ||||
|        #"/var/lib/matrix-synapse/slack-registration.yaml" | ||||
|        #"/var/lib/matrix-synapse/whatsapp-registration.yaml" | ||||
|     ]; | ||||
|     server_name = "sealight.xyz"; | ||||
|     registration_shared_secret = "hD9HQGTTDxp0mQsQ5JDsfudWMDiubmZENOgPchIvfBvUlPxlvQSvjoO4wn2L1seU"; | ||||
|     enable_metrics = true; | ||||
|     enable_registration = true; | ||||
|     database_type = "psycopg2"; | ||||
|     database_args = { | ||||
|       database = "matrix-synapse"; | ||||
|     }; | ||||
| 
 | ||||
|     listeners = [ | ||||
|       { | ||||
|         port = 8448; | ||||
|         tls = false; | ||||
|         resources = [{ | ||||
|             compress = true; | ||||
|             names = ["client" "federation"]; | ||||
|           }]; | ||||
|       } | ||||
|       { | ||||
| 	port = 9090; | ||||
| 	type = "metrics"; | ||||
| 	bind_address = "0.0.0.0"; | ||||
| 	resources = [{  | ||||
| 	  compress = false; | ||||
| 	  names = []; | ||||
| 	}]; | ||||
| 	tls = false; | ||||
|       } | ||||
|     ]; | ||||
|     extraConfig = '' | ||||
|       max_upload_size: "50M" | ||||
|       use_presence: false | ||||
|     ''; | ||||
|     ## coturn based TURN server integration (TURN server setup mentioned later), | ||||
|     ## shared secret generated while configuring coturn | ||||
|     ## and reused here (power of Nix being a real programming language) | ||||
|     turn_uris = [ | ||||
|       "turn:turn.sealight.xyz:3478?transport=udp" | ||||
|       "turn:turn.sealight.xyz:3478?transport=tcp" | ||||
|     ]; | ||||
|     turn_shared_secret = config.services.coturn.static-auth-secret; | ||||
|   }; | ||||
| 
 | ||||
| 
 | ||||
|   services.coturn = { | ||||
|     enable = true; | ||||
|     use-auth-secret = true; | ||||
|     static-auth-secret = "jXW1ohIq6wM3NB00xeME3uBihY85xjpkhGoyzBIdwhOpj7gjyxXZu1fwp1lUiYwJ"; | ||||
|     realm = "turn.sealight.xyz"; | ||||
|     min-port = 49111; | ||||
|     max-port = 51111; | ||||
|     no-cli = true; | ||||
|     no-tcp-relay = true; | ||||
|     no-tls = true; | ||||
|     cert = "${config.security.acme.certs."turn.sealight.xyz".directory}/full.pem"; | ||||
|     pkey = "${config.security.acme.certs."turn.sealight.xyz".directory}/key.pem"; | ||||
|     extraConfig = '' | ||||
| 	verbose | ||||
|         user-quota=12 | ||||
|         total-quota=1200 | ||||
|         denied-peer-ip=10.0.0.0-10.255.255.255 | ||||
|         denied-peer-ip=192.168.0.0-192.168.255.255 | ||||
|         denied-peer-ip=172.16.0.0-172.31.255.255 | ||||
| 	denied-peer-ip=0.0.0.0-0.255.255.255 | ||||
| 	denied-peer-ip=100.64.0.0-100.127.255.255 | ||||
| 	denied-peer-ip=127.0.0.0-127.255.255.255 | ||||
| 	denied-peer-ip=169.254.0.0-169.254.255.255 | ||||
| 	denied-peer-ip=192.0.0.0-192.0.0.255 | ||||
| 	denied-peer-ip=192.0.2.0-192.0.2.255 | ||||
| 	denied-peer-ip=192.88.99.0-192.88.99.255 | ||||
| 	denied-peer-ip=198.18.0.0-198.19.255.255 | ||||
| 	denied-peer-ip=198.51.100.0-198.51.100.255 | ||||
| 	denied-peer-ip=203.0.113.0-203.0.113.255 | ||||
| 	denied-peer-ip=240.0.0.0-255.255.255.255 | ||||
|     ''; | ||||
|   }; | ||||
| 
 | ||||
|   security.acme.certs.${config.services.coturn.realm} = { | ||||
|     /* insert here the right configuration to obtain a certificate */ | ||||
|     webroot = "/var/lib/acme/acme-challenge/"; | ||||
|     email = "anish+acme@lakhwara.com"; | ||||
|     postRun = "systemctl restart coturn.service"; | ||||
|     group = "turnserver"; | ||||
|   }; | ||||
| 
 | ||||
|   services.jitsi-meet = { | ||||
|     enable = true; | ||||
|     hostName = "jitsi.sealight.xyz"; | ||||
|   }; | ||||
|   services.jitsi-videobridge.enable = true; | ||||
| 
 | ||||
|   services.mautrix-telegram = { | ||||
|     enable = true; | ||||
|     environmentFile = /etc/secrets/telegram.env; # file containing the appservice and telegram tokens | ||||
|     # The appservice is pre-configured to use SQLite by default. It's also possible to use PostgreSQL. | ||||
|     settings = { | ||||
|       homeserver = { | ||||
|         address = "https://sealight.xyz"; | ||||
|         domain = "sealight.xyz"; | ||||
|       }; | ||||
|       appservice = { | ||||
|         provisioning.enabled = false; | ||||
|         id = "telegram"; | ||||
| 	bot_username = "telegrambridge"; | ||||
|         public = { | ||||
|           enabled = false; | ||||
|           prefix = "/public"; | ||||
|           external = "https://chat.sealight.xyz/public"; | ||||
|         }; | ||||
| 	address = "http://localhost:18787"; | ||||
| 	port = 18787; | ||||
|         # The service uses SQLite by default, but it's also possible to use PostgreSQL instead: | ||||
|         #database = "postgresql:///mautrix-telegram?host=/run/postgresql"; | ||||
|       }; | ||||
|       bridge = { | ||||
|         relaybot.authless_portals = false; | ||||
|         permissions = { | ||||
|           "@aynish:sealight.xyz" = "admin"; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   services.mautrix-whatsapp = { | ||||
|     enable = false; | ||||
|     # The appservice is pre-configured to use SQLite by default. It's also possible to use PostgreSQL. | ||||
|     #configOptions = { | ||||
|     #  homeserver = { | ||||
|     #    address = "https://chat.sealight.xyz"; | ||||
|     #    domain = "sealight.xyz"; | ||||
|     #  }; | ||||
|     #  appservice = { | ||||
|     #    id = "whatsapp"; | ||||
|     #    address = http://localhost:9897; | ||||
|     #    hostname = "0.0.0.0"; | ||||
|     #    port = 9897; | ||||
|     #    database = { | ||||
|     #      type = "sqlite3"; | ||||
|     #      uri = "/var/lib/mautrix-whatsapp/mautrix-whatsapp.db"; | ||||
|     #    }; | ||||
|     #    state_store_path = "/var/lib/mautrix-whatsapp/mx-state.json"; | ||||
|     #    bot = { | ||||
|     #      username = "whatsappbot"; | ||||
|     #      displayname = "WhatsApp bridge bot"; | ||||
|     #      avatar = "mxc://maunium.net/NeXNQarUbrlYBiPCpprYsRqr"; | ||||
|     #    }; | ||||
|     #    as_token = ""; | ||||
|     #    hs_token = ""; | ||||
|     #  }; | ||||
|     #  bridge = { | ||||
|     #    username_template = "whatsapp_{{.}}"; | ||||
|     #    displayname_template = "{{if .Notify}}{{.Notify}}{{else}}{{.Jid}}{{end}} (WA)"; | ||||
|     #    command_prefix = "!wa"; | ||||
|     #    permissions = { | ||||
|     #    	"@aynish:sealight.xyz" = 100; | ||||
|     #    }; | ||||
|     #  }; | ||||
|     #  logging = { | ||||
|     #    directory = "/var/lib/mautrix-whatsapp/logs"; | ||||
|     #    file_name_format = "{{.Date}}-{{.Index}}.log"; | ||||
|     #    file_date_format = "\"2006-01-02\""; | ||||
|     #    file_mode = 384; | ||||
|     #    timestamp_format = "Jan _2, 2006 15:04:05"; | ||||
|     #    print_level = "debug"; | ||||
|     #  }; | ||||
|     #  metrics = { | ||||
|     #    enabled = true; | ||||
|     #    listen  = "http://localhost:5070"; | ||||
|     #  }; | ||||
|     #}; | ||||
|   }; | ||||
| 
 | ||||
|   services.mx-puppet-discord = { | ||||
|     enable = true; | ||||
|     settings = { | ||||
|       bridge = {  | ||||
| 	bindAddress = "localhost"; | ||||
| 	port = 16785; | ||||
|  	domain = "sealight.xyz"; | ||||
|  	homeserverUrl = "https://sealight.xyz"; | ||||
| 	avatarUrl = "https://discord.com/assets/2d20a45d79110dc5bf947137e9d99b66.svg"; | ||||
|       }; | ||||
|       provisioning = { | ||||
| 	whitelist = [ "@aynish:sealight.xyz" ]; | ||||
|       }; | ||||
|       relay = { | ||||
| 	whitelist = [ "@aynish:sealight.xyz" ]; | ||||
|       }; | ||||
|       namePatterns = { | ||||
|         group = ":name"; | ||||
|         room = ":name"; | ||||
|         user = ":name (Discord)"; | ||||
|         userOverride = ":displayname"; | ||||
|       }; | ||||
|       presence = { | ||||
|         enabled = false; | ||||
|       }; | ||||
|     }; | ||||
|     serviceDependencies = ["matrix-synapse.service"]; | ||||
|   }; | ||||
| 
 | ||||
|   #services.mx-puppet-slack= { | ||||
|     #enable = false; | ||||
|     #settings = { | ||||
|     #  bridge = {  | ||||
|     #    bindAddress = "localhost"; | ||||
|     #    port = 16786; | ||||
|     #    domain = "sealight.xyz"; | ||||
|     #    homeserverUrl = "https://sealight.xyz"; | ||||
|     #  }; | ||||
|     #  provisioning = { | ||||
|     #    whitelist = [ "@aynish:sealight.xyz" ]; | ||||
|     #  }; | ||||
|     #  relay = { | ||||
|     #    whitelist = [ "@aynish:sealight.xyz" ]; | ||||
|     #  }; | ||||
|     #  namePatterns = { | ||||
|     #    group = ":name"; | ||||
|     #    room = ":name[:team? - :team,]"; | ||||
|     #    user = ":name (Slack)"; | ||||
|     #    userOverride = ":displayname"; | ||||
|     #  }; | ||||
|     #  presence = { | ||||
|     #    enabled = false; | ||||
|     #  }; | ||||
|     #  oauth = { | ||||
|     #    enabled = false; | ||||
|     #  }; | ||||
|     #}; | ||||
|     #serviceDependencies = ["matrix-synapse.service"]; | ||||
|   #}; | ||||
| 
 | ||||
|   services.heisenbridge = { | ||||
|     enable = true; | ||||
|     homeserver = "https://sealight.xyz"; | ||||
|     listenPort = 14456; | ||||
|     appServiceToken = "wyujLh8kjpmk2bfKeEE3sZ2gWOEUBKK5";  | ||||
|     homeserverToken = "yEHs7lthD2ZHUibJOAv1APaFhEjxN5PT"; | ||||
|   }; | ||||
| 
 | ||||
|   services.postgresql = { | ||||
|     enable = true; | ||||
|     ## postgresql user and db name remains in the | ||||
|     ## service.matrix-synapse.database_args setting which | ||||
|     ## by default is matrix-synapse | ||||
|     initialScript = pkgs.writeText "synapse-init.sql" '' | ||||
|         CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD "Da0?H*9i{x?,]|'kq@iBwlIzu"; | ||||
|         CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" | ||||
|             TEMPLATE template0 | ||||
|             LC_COLLATE = "C" | ||||
|             LC_CTYPE = "C"; | ||||
|         ''; | ||||
|   }; | ||||
| 
 | ||||
|   networking.firewall = let | ||||
|   range = with config.services.coturn; [ { | ||||
|       from = min-port; | ||||
|       to = max-port; | ||||
|     } ];  | ||||
|     in { | ||||
|     enable = true; | ||||
|     allowedUDPPortRanges = range; # coturn | ||||
|     allowedTCPPortRanges = range; | ||||
|     allowedTCPPorts = [ | ||||
|       22    # SSH | ||||
|       8448  # Matrix federation | ||||
|       8008 | ||||
|       80  | ||||
|       443 | ||||
|       3478 # Coturn service | ||||
|       5349 # Coturn service | ||||
|       9090 # Synapse Metrics | ||||
|     ]; | ||||
|     allowedUDPPorts = [  | ||||
|       3478 | ||||
|       5349 # Coturn service | ||||
|     ]; | ||||
|   }; | ||||
| 
 | ||||
|  nixpkgs.overlays = [ | ||||
|     (self: super: { | ||||
|         element-web = super.element-web.override { | ||||
|             conf = { | ||||
|                  default_server_config = { | ||||
|                     "m.homeserver" = { | ||||
|                         "base_url" = "https://chat.sealight.xyz"; | ||||
|                         "server_name" = "sealight.xyz"; | ||||
|                     }; | ||||
|                     "m.identity_server" = { | ||||
|                         "base_url" = "https://vector.im"; | ||||
|                     }; | ||||
|                  }; | ||||
| 
 | ||||
|                  ## jitsi will be setup later, | ||||
|                  ## but we need to add to Riot configuration | ||||
|                  jitsi.preferredDomain = "jitsi.sealight.xyz"; | ||||
|             }; | ||||
|         }; | ||||
|     }) | ||||
|   ]; | ||||
| 
 | ||||
|   services.nginx = { | ||||
|    enable = true; | ||||
|    virtualHosts = { | ||||
| 
 | ||||
|      "sealight.xyz" = { | ||||
|        forceSSL = true; | ||||
|        enableACME = true; | ||||
|        locations."/" = { | ||||
|          root = "/var/www/sealight.xyz"; | ||||
|        }; | ||||
|        locations."/_matrix" = { | ||||
|          proxyPass = "http://localhost:8448"; | ||||
|        }; | ||||
|        locations."/slackbridge" = { | ||||
|          proxyPass = "http://localhost:9899"; | ||||
|        }; | ||||
|      }; | ||||
| 
 | ||||
|      ## virtual host for Synapse | ||||
|      "chat.sealight.xyz" = { | ||||
|        forceSSL = true; | ||||
|        enableACME = true; | ||||
|        #useACMEHost = "sealight.xyz"; | ||||
|        locations."/" = { | ||||
|          proxyPass = "http://localhost:8448"; | ||||
|        }; | ||||
|      }; | ||||
| 
 | ||||
|      ## virtual host for Riot/Web | ||||
|      "element.sealight.xyz" = { | ||||
|        forceSSL = true; | ||||
|        enableACME = true; | ||||
|        #useACMEHost = "sealight.xyz"; | ||||
| 
 | ||||
|        ## root points to the riot-web package content, also configured via Nix | ||||
|        locations."/" = { | ||||
|            root = pkgs.element-web; | ||||
|        }; | ||||
|      }; | ||||
|   | ||||
|      ${config.services.jitsi-meet.hostName} = { | ||||
|        enableACME = true; | ||||
|        forceSSL = true; | ||||
|      }; | ||||
|    }; | ||||
|    ## other nginx specific best practices | ||||
|    recommendedGzipSettings = true; | ||||
|    recommendedOptimisation = true; | ||||
|    recommendedTlsSettings = true; | ||||
|   }; | ||||
| 
 | ||||
|   environment.systemPackages = with pkgs; [ matrix-appservice-slack ]; | ||||
| } | ||||
							
								
								
									
										96
									
								
								profiles/helix-zone/mautrix-whatsapp.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								profiles/helix-zone/mautrix-whatsapp.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,96 @@ | |||
| { lib, config, pkgs, ... }: | ||||
| 
 | ||||
| with lib; | ||||
| 
 | ||||
| let | ||||
|   cfg = config.services.mautrix-whatsapp; | ||||
| 
 | ||||
|   configFile = pkgs.runCommand "mautrix-whatsapp" { | ||||
|     buildInputs = [ pkgs.mautrix-whatsapp pkgs.remarshal ]; | ||||
|     preferLocalBuild = true; | ||||
|   } '' | ||||
|     mkdir -p $out | ||||
|     ${pkgs.remarshal}/bin/json2yaml -i ${pkgs.writeText "config.json" (builtins.toJSON cfg.configOptions)} \ | ||||
|       -o $out/config.yaml | ||||
| 
 | ||||
|     ${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp -c $out/config.yaml -g -r $out/registration.yaml | ||||
|   ''; | ||||
| 
 | ||||
| in | ||||
| { | ||||
|   options.services.mautrix-whatsapp = { | ||||
|     enable = mkEnableOption "Mautrix-whatsapp, a puppeting bridge between Matrix and WhatsApp."; | ||||
| 
 | ||||
|     configOptions = mkOption { | ||||
|       type = types.attrs; | ||||
|       description = '' | ||||
|         This options will be transform in YAML configuration file for the bridge | ||||
| 
 | ||||
|         Look <link xlink:href="https://github.com/tulir/mautrix-whatsapp/wiki/Bridge-setup">here</link> for documentation. | ||||
|       ''; | ||||
|       example = { | ||||
|         configOptions = { | ||||
|           homeserver = { | ||||
|             address = https://matrix.org; | ||||
|             domain = "matrix.org"; | ||||
|           }; | ||||
|           appservice = { | ||||
|             address = http://localhost:8080; | ||||
|             hostname = "0.0.0.0"; | ||||
|             port = 8080; | ||||
|             database = { | ||||
|               type = "sqlite3"; | ||||
|               uri = "/var/lib/mautrix-whatsapp/mautrix-whatsapp.db"; | ||||
|             }; | ||||
|             state_store_path = "/var/lib/mautrix-whatsapp/mx-state.json"; | ||||
|             id = "whatsapp"; | ||||
|             bot = { | ||||
|               username = "whatsappbot"; | ||||
|               displayname = "WhatsApp bridge bot"; | ||||
|               avatar = "mxc://maunium.net/NeXNQarUbrlYBiPCpprYsRqr"; | ||||
|             }; | ||||
|             as_token = ""; | ||||
|             hs_token = ""; | ||||
|           }; | ||||
|           bridge = { | ||||
|             username_template = "whatsapp_{{.}}"; | ||||
|             displayname_template = "{{if .Notify}}{{.Notify}}{{else}}{{.Jid}}{{end}} (WA)"; | ||||
|             command_prefix = "!wa"; | ||||
|             permissions = { | ||||
|               "@example:matrix.org" = 100; | ||||
|             }; | ||||
|           }; | ||||
|           logging = { | ||||
|             directory = "/var/lib/mautrix-whatsapp/logs"; | ||||
|             file_name_format = "{{.Date}}-{{.Index}}.log"; | ||||
|             file_date_format = "\"2006-01-02\""; | ||||
|             file_mode = 384; | ||||
|             timestamp_format = "Jan _2, 2006 15:04:05"; | ||||
|             print_level = "debug"; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = mkIf cfg.enable { | ||||
|     systemd.services.mautrix-whatsapp = { | ||||
|       description = "Mautrix-WhatsApp Service - A WhatsApp bridge for Matrix"; | ||||
|       after = [ "network.target" "matrix-synapse.service" ]; | ||||
|       wantedBy = [ "multi-user.target" ]; | ||||
| 
 | ||||
|       serviceConfig = { | ||||
|         DynamicUser = true; | ||||
|         StateDirectory = "mautrix-whatsapp"; | ||||
| 	LoggingDir = "mautrix-whatsapp"; | ||||
|         ExecStart = '' | ||||
|           ${pkgs.mautrix-whatsapp}/bin/mautrix-whatsapp -c "${configFile}/config.yaml" | ||||
|         ''; | ||||
|         Restart = "on-failure"; | ||||
|       }; | ||||
|     }; | ||||
| 
 | ||||
|     #services.matrix-synapse.app_service_config_files = [ "${configFile}/registration.yaml" ]; | ||||
| 
 | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										112
									
								
								profiles/helix-zone/mod-heisenbridge.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								profiles/helix-zone/mod-heisenbridge.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| { config, lib, pkgs, ... }: with lib; let | ||||
|   cfg = config.services.heisenbridge; | ||||
| 
 | ||||
|   heisenbridgeAppserviceConfig = { | ||||
|     id = "heisenbridge"; | ||||
|     url = "http://${cfg.listenAddress}:${toString cfg.listenPort}"; | ||||
|     as_token = cfg.appServiceToken; | ||||
|     hs_token = cfg.homeserverToken; | ||||
|     rate_limited = false; | ||||
|     sender_localpart = cfg.senderLocalpart; | ||||
|     namespaces = { | ||||
|       users = [{ regex = "@irc_.*"; exclusive = true; }]; | ||||
|       aliases = [ ]; | ||||
|       rooms = [ ]; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   heisenbridgeConfigYaml = pkgs.writeText "heisenbridge.yaml" ( | ||||
|     generators.toYAML { } heisenbridgeAppserviceConfig); | ||||
| in | ||||
| { | ||||
|   options = { | ||||
|     services.heisenbridge = { | ||||
|       enable = mkEnableOption "heisenbridge, a bouncer-style Matrix IRC bridge."; | ||||
|       identd.enable = mkEnableOption "identd for heisenbridge" // { | ||||
|         default = true; | ||||
|       }; | ||||
|       homeserver = mkOption { | ||||
|         type = types.str; | ||||
|         default = "http://localhost:8008"; | ||||
|         description = "The URL of the Matrix homeserver."; | ||||
|       }; | ||||
|       listenAddress = mkOption { | ||||
|         type = types.str; | ||||
|         default = "127.0.0.1"; | ||||
|         description = "The address for heisenbridge to listen on."; | ||||
|       }; | ||||
|       listenPort = mkOption { | ||||
|         type = types.int; | ||||
|         default = 9898; | ||||
|         description = "The port for heisenbridge to listen on."; | ||||
|       }; | ||||
|       senderLocalpart = mkOption { | ||||
|         type = types.str; | ||||
|         default = "heisenbridge"; | ||||
|         description = "The localpart of the heisenbridge admin bot's username."; | ||||
|       }; | ||||
|       ownerId = mkOption { | ||||
|         type = types.nullOr types.str; | ||||
|         default = null; | ||||
|         description = '' | ||||
|           The owner MXID (for example, @user:homeserver) of the bridge. If | ||||
|           unspecified, the first talking local user will claim the bridge. | ||||
|         ''; | ||||
|       }; | ||||
|       appServiceToken = mkOption { | ||||
|         type = types.str; | ||||
|         description = '' | ||||
|           This is the token that the app service should use as its access_token | ||||
|           when using the Client-Server API. This can be anything you want. | ||||
|         ''; | ||||
|       }; | ||||
|       homeserverToken = mkOption { | ||||
|         type = types.str; | ||||
|         description = '' | ||||
|           This is the token that the homeserver will use when sending requests | ||||
|           to the app service. This can be anything you want. | ||||
|         ''; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = mkIf cfg.enable { | ||||
|     meta.maintainers = [ maintainers.sumnerevans ]; | ||||
| 
 | ||||
|     services.matrix-synapse.app_service_config_files = [ | ||||
|       heisenbridgeConfigYaml | ||||
|     ]; | ||||
| 
 | ||||
|     # Create a user for heisenbridge. | ||||
|     users.users.heisenbridge = { | ||||
|       group = "heisenbridge"; | ||||
|       isSystemUser = true; | ||||
|     }; | ||||
|     users.groups.heisenbridge = { }; | ||||
| 
 | ||||
|     # Open ports for identd. | ||||
|     networking.firewall.allowedTCPPorts = mkIf cfg.identd.enable [ 113 ]; | ||||
| 
 | ||||
|     systemd.services.heisenbridge = { | ||||
|       description = "Heisenbridge Matrix IRC bridge"; | ||||
|       after = ["matrix-synapse.service"]; | ||||
|       wantedBy = [ "multi-user.target" ]; | ||||
|       serviceConfig = { | ||||
|         ExecStart = '' | ||||
|           ${pkgs.heisenbridge}/bin/heisenbridge \ | ||||
|             --config ${heisenbridgeConfigYaml} \ | ||||
|             --verbose --verbose \ | ||||
|             --listen-address ${cfg.listenAddress} \ | ||||
|             --listen-port ${toString cfg.listenPort} \ | ||||
|             --uid heisenbridge \ | ||||
|             --gid heisenbridge \ | ||||
|             ${optionalString cfg.identd.enable "--identd"} \ | ||||
|             ${optionalString (cfg.ownerId != null) "--owner ${cfg.ownerId}"} \ | ||||
|             ${cfg.homeserver} | ||||
|         ''; | ||||
|         Restart = "on-failure"; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										124
									
								
								profiles/helix-zone/mod-mx-puppet-slack.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								profiles/helix-zone/mod-mx-puppet-slack.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,124 @@ | |||
| { config, pkgs, lib, ... }: | ||||
| 
 | ||||
| with lib; | ||||
| 
 | ||||
| let | ||||
|   dataDir = "/var/lib/mx-puppet-slack"; | ||||
|   registrationFile = "${dataDir}/slack-registration.yaml"; | ||||
|   cfg = config.services.mx-puppet-slack; | ||||
|   settingsFormat = pkgs.formats.json {}; | ||||
|   settingsFile = settingsFormat.generate "mx-puppet-slack-config.json" cfg.settings; | ||||
|   mx-puppet-slack = pkgs.callPackage ./pkg-mx-puppet-slack.nix { }; | ||||
| 
 | ||||
| in { | ||||
|   options = { | ||||
|     services.mx-puppet-slack = { | ||||
|       enable = mkEnableOption '' | ||||
|         mx-puppet-slack is a slack puppeting bridge for matrix. | ||||
|         It handles bridging private and group DMs, as well as Guilds (servers) | ||||
|       ''; | ||||
| 
 | ||||
|       settings = mkOption rec { | ||||
|         apply = recursiveUpdate default; | ||||
|         inherit (settingsFormat) type; | ||||
|         default = { | ||||
|           bridge.port = 8434; | ||||
|           presence = { | ||||
|             enabled = true; | ||||
|             interval = 500; | ||||
|           }; | ||||
|           provisioning.whitelist = [ ]; | ||||
|           relay.whitelist = [ ]; | ||||
| 
 | ||||
|           # variables are preceded by a colon. | ||||
|           namePatterns = { | ||||
|             user = ":name"; | ||||
|             userOverride = ":displayname"; | ||||
|             room = ":name"; | ||||
|             group = ":name"; | ||||
|           }; | ||||
| 
 | ||||
|           #defaults to sqlite but can be configured to use postgresql with | ||||
|           #connstring | ||||
|           database.filename = "${dataDir}/database.db"; | ||||
|           logging = { | ||||
|             console = "info"; | ||||
|             lineDateFormat = "MMM-D HH:mm:ss.SSS"; | ||||
|           }; | ||||
|         }; | ||||
|         example = literalExpression '' | ||||
|           { | ||||
|             bridge = { | ||||
|               bindAddress = "localhost"; | ||||
|               domain = "example.com"; | ||||
|               homeserverUrl = "https://example.com"; | ||||
|             }; | ||||
| 
 | ||||
|             provisioning.whitelist = [ "@admin:example.com" ]; | ||||
|             relay.whitelist = [ "@.*:example.com" ]; | ||||
|           } | ||||
|         ''; | ||||
|         description = '' | ||||
|           <filename>config.yaml</filename> configuration as a Nix attribute set. | ||||
|           Configuration options should match those described in | ||||
|           <link xlink:href="https://github.com/matrix-slack/mx-puppet-slack/blob/master/sample.config.yaml"> | ||||
|           sample.config.yaml</link>. | ||||
|         ''; | ||||
|       }; | ||||
|       serviceDependencies = mkOption { | ||||
|         type = with types; listOf str; | ||||
|         default = optional config.services.matrix-synapse.enable "matrix-synapse.service"; | ||||
|         description = '' | ||||
|           List of Systemd services to require and wait for when starting the application service. | ||||
|         ''; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   config = mkIf cfg.enable { | ||||
|     systemd.services.mx-puppet-slack = { | ||||
|       description = '' | ||||
|         mx-puppet-slack is a slack puppeting bridge for matrix. | ||||
|         It handles bridging private and group DMs, as well as Guilds (servers). | ||||
|       ''; | ||||
| 
 | ||||
|       wantedBy = [ "multi-user.target" ]; | ||||
|       wants = [ "network-online.target" ] ++ cfg.serviceDependencies; | ||||
|       after = [ "network-online.target" ] ++ cfg.serviceDependencies; | ||||
| 
 | ||||
|       preStart = '' | ||||
|         # generate the appservice's registration file if absent | ||||
|         if [ ! -f '${registrationFile}' ]; then | ||||
|           ${mx-puppet-slack}/bin/mx-puppet-slack -r -c ${settingsFile} \ | ||||
|           -f ${registrationFile} | ||||
|         fi | ||||
|       ''; | ||||
| 
 | ||||
|       serviceConfig = { | ||||
|         Type = "simple"; | ||||
|         Restart = "always"; | ||||
| 
 | ||||
|         ProtectSystem = "strict"; | ||||
|         ProtectHome = true; | ||||
|         ProtectKernelTunables = true; | ||||
|         ProtectKernelModules = true; | ||||
|         ProtectControlGroups = true; | ||||
| 
 | ||||
|         DynamicUser = true; | ||||
|         PrivateTmp = true; | ||||
|         WorkingDirectory = mx-puppet-slack; | ||||
|         StateDirectory = baseNameOf dataDir; | ||||
|         UMask = 0027; | ||||
| 
 | ||||
|         ExecStart = '' | ||||
|           ${mx-puppet-slack}/bin/mx-puppet-slack \ | ||||
|             -c ${settingsFile} \ | ||||
|             -f ${registrationFile} | ||||
|         ''; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   meta.maintainers = with maintainers; [ chickensoupwithrice ]; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										159
									
								
								profiles/helix-zone/monitoring.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								profiles/helix-zone/monitoring.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,159 @@ | |||
| { config, pkgs, ... }: { | ||||
|   # grafana configuration | ||||
|   #services.grafana = { | ||||
|   #  enable = true; | ||||
|   #  domain = "grafana.mossnet.lan"; | ||||
|   #  port = 2342; | ||||
|   #  addr = "127.0.0.1"; | ||||
|   #}; | ||||
|   # | ||||
|   ## nginx reverse proxy | ||||
|   #services.nginx.virtualHosts.${config.services.grafana.domain} = { | ||||
|   #  locations."/" = { | ||||
|   #      proxyPass = "http://127.0.0.1:${toString config.services.grafana.port}"; | ||||
|   #      proxyWebsockets = true; | ||||
|   #  }; | ||||
|   #}; | ||||
| 
 | ||||
|   services.prometheus = { | ||||
|     enable = true; | ||||
|     port = 9001; | ||||
|     exporters = { | ||||
|       node = { | ||||
| 	enable = true; | ||||
| 	enabledCollectors = [ "systemd" ]; | ||||
| 	port = 9002; | ||||
|       }; | ||||
|     }; | ||||
|     rules = [ | ||||
|       '' | ||||
| groups: | ||||
| - name: synapse | ||||
|   rules: | ||||
|   - record: "synapse_federation_transaction_queue_pendingEdus:total" | ||||
|     expr: "sum(synapse_federation_transaction_queue_pendingEdus or absent(synapse_federation_transaction_queue_pendingEdus)*0)" | ||||
|   - record: "synapse_federation_transaction_queue_pendingPdus:total" | ||||
|     expr:   "sum(synapse_federation_transaction_queue_pendingPdus or absent(synapse_federation_transaction_queue_pendingPdus)*0)" | ||||
|   - record: 'synapse_http_server_request_count:method' | ||||
|     labels: | ||||
|       servlet: "" | ||||
|     expr: "sum(synapse_http_server_request_count) by (method)" | ||||
|   - record: 'synapse_http_server_request_count:servlet' | ||||
|     labels: | ||||
|       method: "" | ||||
|     expr: 'sum(synapse_http_server_request_count) by (servlet)' | ||||
| 
 | ||||
|   - record: 'synapse_http_server_request_count:total' | ||||
|     labels: | ||||
|       servlet: "" | ||||
|     expr: 'sum(synapse_http_server_request_count:by_method) by (servlet)' | ||||
| 
 | ||||
|   - record: 'synapse_cache:hit_ratio_5m' | ||||
|     expr: 'rate(synapse_util_caches_cache:hits[5m]) / rate(synapse_util_caches_cache:total[5m])' | ||||
|   - record: 'synapse_cache:hit_ratio_30s' | ||||
|     expr: 'rate(synapse_util_caches_cache:hits[30s]) / rate(synapse_util_caches_cache:total[30s])' | ||||
| 
 | ||||
|   - record: 'synapse_federation_client_sent' | ||||
|     labels: | ||||
|       type: "EDU" | ||||
|     expr: 'synapse_federation_client_sent_edus + 0' | ||||
|   - record: 'synapse_federation_client_sent' | ||||
|     labels: | ||||
|       type: "PDU" | ||||
|     expr: 'synapse_federation_client_sent_pdu_destinations:count + 0' | ||||
|   - record: 'synapse_federation_client_sent' | ||||
|     labels: | ||||
|       type: "Query" | ||||
|     expr: 'sum(synapse_federation_client_sent_queries) by (job)' | ||||
| 
 | ||||
|   - record: 'synapse_federation_server_received' | ||||
|     labels: | ||||
|       type: "EDU" | ||||
|     expr: 'synapse_federation_server_received_edus + 0' | ||||
|   - record: 'synapse_federation_server_received' | ||||
|     labels: | ||||
|       type: "PDU" | ||||
|     expr: 'synapse_federation_server_received_pdus + 0' | ||||
|   - record: 'synapse_federation_server_received' | ||||
|     labels: | ||||
|       type: "Query" | ||||
|     expr: 'sum(synapse_federation_server_received_queries) by (job)' | ||||
| 
 | ||||
|   - record: 'synapse_federation_transaction_queue_pending' | ||||
|     labels: | ||||
|       type: "EDU" | ||||
|     expr: 'synapse_federation_transaction_queue_pending_edus + 0' | ||||
|   - record: 'synapse_federation_transaction_queue_pending' | ||||
|     labels: | ||||
|       type: "PDU" | ||||
|     expr: 'synapse_federation_transaction_queue_pending_pdus + 0' | ||||
| 
 | ||||
|   - record: synapse_storage_events_persisted_by_source_type | ||||
|     expr: sum without(type, origin_type, origin_entity) (synapse_storage_events_persisted_events_sep{origin_type="remote"}) | ||||
|     labels: | ||||
|       type: remote | ||||
|   - record: synapse_storage_events_persisted_by_source_type | ||||
|     expr: sum without(type, origin_type, origin_entity) (synapse_storage_events_persisted_events_sep{origin_entity="*client*",origin_type="local"}) | ||||
|     labels: | ||||
|       type: local | ||||
|   - record: synapse_storage_events_persisted_by_source_type | ||||
|     expr: sum without(type, origin_type, origin_entity) (synapse_storage_events_persisted_events_sep{origin_entity!="*client*",origin_type="local"}) | ||||
|     labels: | ||||
|       type: bridges | ||||
|   - record: synapse_storage_events_persisted_by_event_type | ||||
|     expr: sum without(origin_entity, origin_type) (synapse_storage_events_persisted_events_sep) | ||||
|   - record: synapse_storage_events_persisted_by_origin | ||||
|     expr: sum without(type) (synapse_storage_events_persisted_events_sep) | ||||
|       '' | ||||
|     ]; | ||||
|     scrapeConfigs = [ | ||||
|       { | ||||
| 	job_name = "helix"; | ||||
| 	static_configs = [{ | ||||
| 	  targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.node.port}" ]; | ||||
| 	}]; | ||||
|       } | ||||
|       { | ||||
| 	job_name = "synapse"; | ||||
| 	metrics_path = "/_synapse/metrics"; | ||||
| 	static_configs = [{ | ||||
| 	  targets = [ "localhost:9090" ]; | ||||
|       }]; | ||||
|       } | ||||
|       { | ||||
|         job_name = "gitea"; | ||||
|         static_configs = [{ | ||||
|           targets = [ "localhost:3001" ]; | ||||
|         }]; | ||||
|       } | ||||
|     ]; | ||||
|   }; | ||||
| 
 | ||||
|   networking.firewall = { | ||||
|     enable = true; | ||||
|     allowedTCPPorts = [ 9001 ]; | ||||
|   }; | ||||
| 
 | ||||
|   services.nginx.virtualHosts."sealight.xyz" = { | ||||
|     locations."/metrics" = { | ||||
|       #basicAuth = { anish = "password"; }; | ||||
|       proxyPass = "http://localhost:9001"; | ||||
|     }; | ||||
|   }; | ||||
| 
 | ||||
|   services.loki = { | ||||
|     enable = true; | ||||
|     configFile = /var/loki-config.yaml; | ||||
|   }; | ||||
| 
 | ||||
|   systemd.services.promtail = { | ||||
|     description = "Promtail service for Loki"; | ||||
|     wantedBy = [ "multi-user.target" ]; | ||||
| 
 | ||||
|     serviceConfig = { | ||||
|       ExecStart = '' | ||||
|         ${pkgs.grafana-loki}/bin/promtail --config.file ${/var/promtail.yaml} | ||||
|       ''; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										17
									
								
								profiles/helix-zone/node-composition.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								profiles/helix-zone/node-composition.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| # This file has been generated by node2nix 1.9.0. Do not edit! | ||||
| 
 | ||||
| {pkgs ? import <nixpkgs> { | ||||
|     inherit system; | ||||
|   }, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-12_x"}: | ||||
| 
 | ||||
| let | ||||
|   nodeEnv = import ./node-env.nix { | ||||
|     inherit (pkgs) stdenv lib python2 runCommand writeTextFile writeShellScript; | ||||
|     inherit pkgs nodejs; | ||||
|     libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null; | ||||
|   }; | ||||
| in | ||||
| import ./node-packages.nix { | ||||
|   inherit (pkgs) fetchurl nix-gitignore stdenv lib fetchgit; | ||||
|   inherit nodeEnv; | ||||
| } | ||||
							
								
								
									
										588
									
								
								profiles/helix-zone/node-env.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										588
									
								
								profiles/helix-zone/node-env.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,588 @@ | |||
| # This file originates from node2nix | ||||
| 
 | ||||
| {lib, stdenv, nodejs, python2, pkgs, libtool, runCommand, writeTextFile, writeShellScript}: | ||||
| 
 | ||||
| let | ||||
|   # Workaround to cope with utillinux in Nixpkgs 20.09 and util-linux in Nixpkgs master | ||||
|   utillinux = if pkgs ? utillinux then pkgs.utillinux else pkgs.util-linux; | ||||
| 
 | ||||
|   python = if nodejs ? python then nodejs.python else python2; | ||||
| 
 | ||||
|   # Create a tar wrapper that filters all the 'Ignoring unknown extended header keyword' noise | ||||
|   tarWrapper = runCommand "tarWrapper" {} '' | ||||
|     mkdir -p $out/bin | ||||
| 
 | ||||
|     cat > $out/bin/tar <<EOF | ||||
|     #! ${stdenv.shell} -e | ||||
|     $(type -p tar) "\$@" --warning=no-unknown-keyword --delay-directory-restore | ||||
|     EOF | ||||
| 
 | ||||
|     chmod +x $out/bin/tar | ||||
|   ''; | ||||
| 
 | ||||
|   # Function that generates a TGZ file from a NPM project | ||||
|   buildNodeSourceDist = | ||||
|     { name, version, src, ... }: | ||||
| 
 | ||||
|     stdenv.mkDerivation { | ||||
|       name = "node-tarball-${name}-${version}"; | ||||
|       inherit src; | ||||
|       buildInputs = [ nodejs ]; | ||||
|       buildPhase = '' | ||||
|         export HOME=$TMPDIR | ||||
|         tgzFile=$(npm pack | tail -n 1) # Hooks to the pack command will add output (https://docs.npmjs.com/misc/scripts) | ||||
|       ''; | ||||
|       installPhase = '' | ||||
|         mkdir -p $out/tarballs | ||||
|         mv $tgzFile $out/tarballs | ||||
|         mkdir -p $out/nix-support | ||||
|         echo "file source-dist $out/tarballs/$tgzFile" >> $out/nix-support/hydra-build-products | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
|   # Common shell logic | ||||
|   installPackage = writeShellScript "install-package" '' | ||||
|     installPackage() { | ||||
|       local packageName=$1 src=$2 | ||||
| 
 | ||||
|       local strippedName | ||||
| 
 | ||||
|       local DIR=$PWD | ||||
|       cd $TMPDIR | ||||
| 
 | ||||
|       unpackFile $src | ||||
| 
 | ||||
|       # Make the base dir in which the target dependency resides first | ||||
|       mkdir -p "$(dirname "$DIR/$packageName")" | ||||
| 
 | ||||
|       if [ -f "$src" ] | ||||
|       then | ||||
|           # Figure out what directory has been unpacked | ||||
|           packageDir="$(find . -maxdepth 1 -type d | tail -1)" | ||||
| 
 | ||||
|           # Restore write permissions to make building work | ||||
|           find "$packageDir" -type d -exec chmod u+x {} \; | ||||
|           chmod -R u+w "$packageDir" | ||||
| 
 | ||||
|           # Move the extracted tarball into the output folder | ||||
|           mv "$packageDir" "$DIR/$packageName" | ||||
|       elif [ -d "$src" ] | ||||
|       then | ||||
|           # Get a stripped name (without hash) of the source directory. | ||||
|           # On old nixpkgs it's already set internally. | ||||
|           if [ -z "$strippedName" ] | ||||
|           then | ||||
|               strippedName="$(stripHash $src)" | ||||
|           fi | ||||
| 
 | ||||
|           # Restore write permissions to make building work | ||||
|           chmod -R u+w "$strippedName" | ||||
| 
 | ||||
|           # Move the extracted directory into the output folder | ||||
|           mv "$strippedName" "$DIR/$packageName" | ||||
|       fi | ||||
| 
 | ||||
|       # Change to the package directory to install dependencies | ||||
|       cd "$DIR/$packageName" | ||||
|     } | ||||
|   ''; | ||||
| 
 | ||||
|   # Bundle the dependencies of the package | ||||
|   # | ||||
|   # Only include dependencies if they don't exist. They may also be bundled in the package. | ||||
|   includeDependencies = {dependencies}: | ||||
|     lib.optionalString (dependencies != []) ( | ||||
|       '' | ||||
|         mkdir -p node_modules | ||||
|         cd node_modules | ||||
|       '' | ||||
|       + (lib.concatMapStrings (dependency: | ||||
|         '' | ||||
|           if [ ! -e "${dependency.name}" ]; then | ||||
|               ${composePackage dependency} | ||||
|           fi | ||||
|         '' | ||||
|       ) dependencies) | ||||
|       + '' | ||||
|         cd .. | ||||
|       '' | ||||
|     ); | ||||
| 
 | ||||
|   # Recursively composes the dependencies of a package | ||||
|   composePackage = { name, packageName, src, dependencies ? [], ... }@args: | ||||
|     builtins.addErrorContext "while evaluating node package '${packageName}'" '' | ||||
|       installPackage "${packageName}" "${src}" | ||||
|       ${includeDependencies { inherit dependencies; }} | ||||
|       cd .. | ||||
|       ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} | ||||
|     ''; | ||||
| 
 | ||||
|   pinpointDependencies = {dependencies, production}: | ||||
|     let | ||||
|       pinpointDependenciesFromPackageJSON = writeTextFile { | ||||
|         name = "pinpointDependencies.js"; | ||||
|         text = '' | ||||
|           var fs = require('fs'); | ||||
|           var path = require('path'); | ||||
| 
 | ||||
|           function resolveDependencyVersion(location, name) { | ||||
|               if(location == process.env['NIX_STORE']) { | ||||
|                   return null; | ||||
|               } else { | ||||
|                   var dependencyPackageJSON = path.join(location, "node_modules", name, "package.json"); | ||||
| 
 | ||||
|                   if(fs.existsSync(dependencyPackageJSON)) { | ||||
|                       var dependencyPackageObj = JSON.parse(fs.readFileSync(dependencyPackageJSON)); | ||||
| 
 | ||||
|                       if(dependencyPackageObj.name == name) { | ||||
|                           return dependencyPackageObj.version; | ||||
|                       } | ||||
|                   } else { | ||||
|                       return resolveDependencyVersion(path.resolve(location, ".."), name); | ||||
|                   } | ||||
|               } | ||||
|           } | ||||
| 
 | ||||
|           function replaceDependencies(dependencies) { | ||||
|               if(typeof dependencies == "object" && dependencies !== null) { | ||||
|                   for(var dependency in dependencies) { | ||||
|                       var resolvedVersion = resolveDependencyVersion(process.cwd(), dependency); | ||||
| 
 | ||||
|                       if(resolvedVersion === null) { | ||||
|                           process.stderr.write("WARNING: cannot pinpoint dependency: "+dependency+", context: "+process.cwd()+"\n"); | ||||
|                       } else { | ||||
|                           dependencies[dependency] = resolvedVersion; | ||||
|                       } | ||||
|                   } | ||||
|               } | ||||
|           } | ||||
| 
 | ||||
|           /* Read the package.json configuration */ | ||||
|           var packageObj = JSON.parse(fs.readFileSync('./package.json')); | ||||
| 
 | ||||
|           /* Pinpoint all dependencies */ | ||||
|           replaceDependencies(packageObj.dependencies); | ||||
|           if(process.argv[2] == "development") { | ||||
|               replaceDependencies(packageObj.devDependencies); | ||||
|           } | ||||
|           replaceDependencies(packageObj.optionalDependencies); | ||||
| 
 | ||||
|           /* Write the fixed package.json file */ | ||||
|           fs.writeFileSync("package.json", JSON.stringify(packageObj, null, 2)); | ||||
|         ''; | ||||
|       }; | ||||
|     in | ||||
|     '' | ||||
|       node ${pinpointDependenciesFromPackageJSON} ${if production then "production" else "development"} | ||||
| 
 | ||||
|       ${lib.optionalString (dependencies != []) | ||||
|         '' | ||||
|           if [ -d node_modules ] | ||||
|           then | ||||
|               cd node_modules | ||||
|               ${lib.concatMapStrings (dependency: pinpointDependenciesOfPackage dependency) dependencies} | ||||
|               cd .. | ||||
|           fi | ||||
|         ''} | ||||
|     ''; | ||||
| 
 | ||||
|   # Recursively traverses all dependencies of a package and pinpoints all | ||||
|   # dependencies in the package.json file to the versions that are actually | ||||
|   # being used. | ||||
| 
 | ||||
|   pinpointDependenciesOfPackage = { packageName, dependencies ? [], production ? true, ... }@args: | ||||
|     '' | ||||
|       if [ -d "${packageName}" ] | ||||
|       then | ||||
|           cd "${packageName}" | ||||
|           ${pinpointDependencies { inherit dependencies production; }} | ||||
|           cd .. | ||||
|           ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} | ||||
|       fi | ||||
|     ''; | ||||
| 
 | ||||
|   # Extract the Node.js source code which is used to compile packages with | ||||
|   # native bindings | ||||
|   nodeSources = runCommand "node-sources" {} '' | ||||
|     tar --no-same-owner --no-same-permissions -xf ${nodejs.src} | ||||
|     mv node-* $out | ||||
|   ''; | ||||
| 
 | ||||
|   # Script that adds _integrity fields to all package.json files to prevent NPM from consulting the cache (that is empty) | ||||
|   addIntegrityFieldsScript = writeTextFile { | ||||
|     name = "addintegrityfields.js"; | ||||
|     text = '' | ||||
|       var fs = require('fs'); | ||||
|       var path = require('path'); | ||||
| 
 | ||||
|       function augmentDependencies(baseDir, dependencies) { | ||||
|           for(var dependencyName in dependencies) { | ||||
|               var dependency = dependencies[dependencyName]; | ||||
| 
 | ||||
|               // Open package.json and augment metadata fields | ||||
|               var packageJSONDir = path.join(baseDir, "node_modules", dependencyName); | ||||
|               var packageJSONPath = path.join(packageJSONDir, "package.json"); | ||||
| 
 | ||||
|               if(fs.existsSync(packageJSONPath)) { // Only augment packages that exist. Sometimes we may have production installs in which development dependencies can be ignored | ||||
|                   console.log("Adding metadata fields to: "+packageJSONPath); | ||||
|                   var packageObj = JSON.parse(fs.readFileSync(packageJSONPath)); | ||||
| 
 | ||||
|                   if(dependency.integrity) { | ||||
|                       packageObj["_integrity"] = dependency.integrity; | ||||
|                   } else { | ||||
|                       packageObj["_integrity"] = "sha1-000000000000000000000000000="; // When no _integrity string has been provided (e.g. by Git dependencies), add a dummy one. It does not seem to harm and it bypasses downloads. | ||||
|                   } | ||||
| 
 | ||||
|                   if(dependency.resolved) { | ||||
|                       packageObj["_resolved"] = dependency.resolved; // Adopt the resolved property if one has been provided | ||||
|                   } else { | ||||
|                       packageObj["_resolved"] = dependency.version; // Set the resolved version to the version identifier. This prevents NPM from cloning Git repositories. | ||||
|                   } | ||||
| 
 | ||||
|                   if(dependency.from !== undefined) { // Adopt from property if one has been provided | ||||
|                       packageObj["_from"] = dependency.from; | ||||
|                   } | ||||
| 
 | ||||
|                   fs.writeFileSync(packageJSONPath, JSON.stringify(packageObj, null, 2)); | ||||
|               } | ||||
| 
 | ||||
|               // Augment transitive dependencies | ||||
|               if(dependency.dependencies !== undefined) { | ||||
|                   augmentDependencies(packageJSONDir, dependency.dependencies); | ||||
|               } | ||||
|           } | ||||
|       } | ||||
| 
 | ||||
|       if(fs.existsSync("./package-lock.json")) { | ||||
|           var packageLock = JSON.parse(fs.readFileSync("./package-lock.json")); | ||||
| 
 | ||||
|           if(![1, 2].includes(packageLock.lockfileVersion)) { | ||||
|              process.stderr.write("Sorry, I only understand lock file versions 1 and 2!\n"); | ||||
|              process.exit(1); | ||||
|           } | ||||
| 
 | ||||
|           if(packageLock.dependencies !== undefined) { | ||||
|               augmentDependencies(".", packageLock.dependencies); | ||||
|           } | ||||
|       } | ||||
|     ''; | ||||
|   }; | ||||
| 
 | ||||
|   # Reconstructs a package-lock file from the node_modules/ folder structure and package.json files with dummy sha1 hashes | ||||
|   reconstructPackageLock = writeTextFile { | ||||
|     name = "addintegrityfields.js"; | ||||
|     text = '' | ||||
|       var fs = require('fs'); | ||||
|       var path = require('path'); | ||||
| 
 | ||||
|       var packageObj = JSON.parse(fs.readFileSync("package.json")); | ||||
| 
 | ||||
|       var lockObj = { | ||||
|           name: packageObj.name, | ||||
|           version: packageObj.version, | ||||
|           lockfileVersion: 1, | ||||
|           requires: true, | ||||
|           dependencies: {} | ||||
|       }; | ||||
| 
 | ||||
|       function augmentPackageJSON(filePath, dependencies) { | ||||
|           var packageJSON = path.join(filePath, "package.json"); | ||||
|           if(fs.existsSync(packageJSON)) { | ||||
|               var packageObj = JSON.parse(fs.readFileSync(packageJSON)); | ||||
|               dependencies[packageObj.name] = { | ||||
|                   version: packageObj.version, | ||||
|                   integrity: "sha1-000000000000000000000000000=", | ||||
|                   dependencies: {} | ||||
|               }; | ||||
|               processDependencies(path.join(filePath, "node_modules"), dependencies[packageObj.name].dependencies); | ||||
|           } | ||||
|       } | ||||
| 
 | ||||
|       function processDependencies(dir, dependencies) { | ||||
|           if(fs.existsSync(dir)) { | ||||
|               var files = fs.readdirSync(dir); | ||||
| 
 | ||||
|               files.forEach(function(entry) { | ||||
|                   var filePath = path.join(dir, entry); | ||||
|                   var stats = fs.statSync(filePath); | ||||
| 
 | ||||
|                   if(stats.isDirectory()) { | ||||
|                       if(entry.substr(0, 1) == "@") { | ||||
|                           // When we encounter a namespace folder, augment all packages belonging to the scope | ||||
|                           var pkgFiles = fs.readdirSync(filePath); | ||||
| 
 | ||||
|                           pkgFiles.forEach(function(entry) { | ||||
|                               if(stats.isDirectory()) { | ||||
|                                   var pkgFilePath = path.join(filePath, entry); | ||||
|                                   augmentPackageJSON(pkgFilePath, dependencies); | ||||
|                               } | ||||
|                           }); | ||||
|                       } else { | ||||
|                           augmentPackageJSON(filePath, dependencies); | ||||
|                       } | ||||
|                   } | ||||
|               }); | ||||
|           } | ||||
|       } | ||||
| 
 | ||||
|       processDependencies("node_modules", lockObj.dependencies); | ||||
| 
 | ||||
|       fs.writeFileSync("package-lock.json", JSON.stringify(lockObj, null, 2)); | ||||
|     ''; | ||||
|   }; | ||||
| 
 | ||||
|   prepareAndInvokeNPM = {packageName, bypassCache, reconstructLock, npmFlags, production}: | ||||
|     let | ||||
|       forceOfflineFlag = if bypassCache then "--offline" else "--registry http://www.example.com"; | ||||
|     in | ||||
|     '' | ||||
|         # Pinpoint the versions of all dependencies to the ones that are actually being used | ||||
|         echo "pinpointing versions of dependencies..." | ||||
|         source $pinpointDependenciesScriptPath | ||||
| 
 | ||||
|         # Patch the shebangs of the bundled modules to prevent them from | ||||
|         # calling executables outside the Nix store as much as possible | ||||
|         patchShebangs . | ||||
| 
 | ||||
|         # Deploy the Node.js package by running npm install. Since the | ||||
|         # dependencies have been provided already by ourselves, it should not | ||||
|         # attempt to install them again, which is good, because we want to make | ||||
|         # it Nix's responsibility. If it needs to install any dependencies | ||||
|         # anyway (e.g. because the dependency parameters are | ||||
|         # incomplete/incorrect), it fails. | ||||
|         # | ||||
|         # The other responsibilities of NPM are kept -- version checks, build | ||||
|         # steps, postprocessing etc. | ||||
| 
 | ||||
|         export HOME=$TMPDIR | ||||
|         cd "${packageName}" | ||||
|         runHook preRebuild | ||||
| 
 | ||||
|         ${lib.optionalString bypassCache '' | ||||
|           ${lib.optionalString reconstructLock '' | ||||
|             if [ -f package-lock.json ] | ||||
|             then | ||||
|                 echo "WARNING: Reconstruct lock option enabled, but a lock file already exists!" | ||||
|                 echo "This will most likely result in version mismatches! We will remove the lock file and regenerate it!" | ||||
|                 rm package-lock.json | ||||
|             else | ||||
|                 echo "No package-lock.json file found, reconstructing..." | ||||
|             fi | ||||
| 
 | ||||
|             node ${reconstructPackageLock} | ||||
|           ''} | ||||
| 
 | ||||
|           node ${addIntegrityFieldsScript} | ||||
|         ''} | ||||
| 
 | ||||
|         npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${lib.optionalString production "--production"} rebuild | ||||
| 
 | ||||
|         if [ "''${dontNpmInstall-}" != "1" ] | ||||
|         then | ||||
|             # NPM tries to download packages even when they already exist if npm-shrinkwrap is used. | ||||
|             rm -f npm-shrinkwrap.json | ||||
| 
 | ||||
|             npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${lib.optionalString production "--production"} install | ||||
|         fi | ||||
|     ''; | ||||
| 
 | ||||
|   # Builds and composes an NPM package including all its dependencies | ||||
|   buildNodePackage = | ||||
|     { name | ||||
|     , packageName | ||||
|     , version | ||||
|     , dependencies ? [] | ||||
|     , buildInputs ? [] | ||||
|     , production ? true | ||||
|     , npmFlags ? "" | ||||
|     , dontNpmInstall ? false | ||||
|     , bypassCache ? false | ||||
|     , reconstructLock ? false | ||||
|     , preRebuild ? "" | ||||
|     , dontStrip ? true | ||||
|     , unpackPhase ? "true" | ||||
|     , buildPhase ? "true" | ||||
|     , meta ? {} | ||||
|     , ... }@args: | ||||
| 
 | ||||
|     let | ||||
|       extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" "dontStrip" "dontNpmInstall" "preRebuild" "unpackPhase" "buildPhase" "meta" ]; | ||||
|     in | ||||
|     stdenv.mkDerivation ({ | ||||
|       name = "${name}-${version}"; | ||||
|       buildInputs = [ tarWrapper python nodejs ] | ||||
|         ++ lib.optional (stdenv.isLinux) utillinux | ||||
|         ++ lib.optional (stdenv.isDarwin) libtool | ||||
|         ++ buildInputs; | ||||
| 
 | ||||
|       inherit nodejs; | ||||
| 
 | ||||
|       inherit dontStrip; # Stripping may fail a build for some package deployments | ||||
|       inherit dontNpmInstall preRebuild unpackPhase buildPhase; | ||||
| 
 | ||||
|       compositionScript = composePackage args; | ||||
|       pinpointDependenciesScript = pinpointDependenciesOfPackage args; | ||||
| 
 | ||||
|       passAsFile = [ "compositionScript" "pinpointDependenciesScript" ]; | ||||
| 
 | ||||
|       installPhase = '' | ||||
|         source ${installPackage} | ||||
| 
 | ||||
|         # Create and enter a root node_modules/ folder | ||||
|         mkdir -p $out/lib/node_modules | ||||
|         cd $out/lib/node_modules | ||||
| 
 | ||||
|         # Compose the package and all its dependencies | ||||
|         source $compositionScriptPath | ||||
| 
 | ||||
|         ${prepareAndInvokeNPM { inherit packageName bypassCache reconstructLock npmFlags production; }} | ||||
| 
 | ||||
|         # Create symlink to the deployed executable folder, if applicable | ||||
|         if [ -d "$out/lib/node_modules/.bin" ] | ||||
|         then | ||||
|             ln -s $out/lib/node_modules/.bin $out/bin | ||||
|         fi | ||||
| 
 | ||||
|         # Create symlinks to the deployed manual page folders, if applicable | ||||
|         if [ -d "$out/lib/node_modules/${packageName}/man" ] | ||||
|         then | ||||
|             mkdir -p $out/share | ||||
|             for dir in "$out/lib/node_modules/${packageName}/man/"* | ||||
|             do | ||||
|                 mkdir -p $out/share/man/$(basename "$dir") | ||||
|                 for page in "$dir"/* | ||||
|                 do | ||||
|                     ln -s $page $out/share/man/$(basename "$dir") | ||||
|                 done | ||||
|             done | ||||
|         fi | ||||
| 
 | ||||
|         # Run post install hook, if provided | ||||
|         runHook postInstall | ||||
|       ''; | ||||
| 
 | ||||
|       meta = { | ||||
|         # default to Node.js' platforms | ||||
|         platforms = nodejs.meta.platforms; | ||||
|       } // meta; | ||||
|     } // extraArgs); | ||||
| 
 | ||||
|   # Builds a node environment (a node_modules folder and a set of binaries) | ||||
|   buildNodeDependencies = | ||||
|     { name | ||||
|     , packageName | ||||
|     , version | ||||
|     , src | ||||
|     , dependencies ? [] | ||||
|     , buildInputs ? [] | ||||
|     , production ? true | ||||
|     , npmFlags ? "" | ||||
|     , dontNpmInstall ? false | ||||
|     , bypassCache ? false | ||||
|     , reconstructLock ? false | ||||
|     , dontStrip ? true | ||||
|     , unpackPhase ? "true" | ||||
|     , buildPhase ? "true" | ||||
|     , ... }@args: | ||||
| 
 | ||||
|     let | ||||
|       extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" ]; | ||||
|     in | ||||
|       stdenv.mkDerivation ({ | ||||
|         name = "node-dependencies-${name}-${version}"; | ||||
| 
 | ||||
|         buildInputs = [ tarWrapper python nodejs ] | ||||
|           ++ lib.optional (stdenv.isLinux) utillinux | ||||
|           ++ lib.optional (stdenv.isDarwin) libtool | ||||
|           ++ buildInputs; | ||||
| 
 | ||||
|         inherit dontStrip; # Stripping may fail a build for some package deployments | ||||
|         inherit dontNpmInstall unpackPhase buildPhase; | ||||
| 
 | ||||
|         includeScript = includeDependencies { inherit dependencies; }; | ||||
|         pinpointDependenciesScript = pinpointDependenciesOfPackage args; | ||||
| 
 | ||||
|         passAsFile = [ "includeScript" "pinpointDependenciesScript" ]; | ||||
| 
 | ||||
|         installPhase = '' | ||||
|           source ${installPackage} | ||||
| 
 | ||||
|           mkdir -p $out/${packageName} | ||||
|           cd $out/${packageName} | ||||
| 
 | ||||
|           source $includeScriptPath | ||||
| 
 | ||||
|           # Create fake package.json to make the npm commands work properly | ||||
|           cp ${src}/package.json . | ||||
|           chmod 644 package.json | ||||
|           ${lib.optionalString bypassCache '' | ||||
|             if [ -f ${src}/package-lock.json ] | ||||
|             then | ||||
|                 cp ${src}/package-lock.json . | ||||
|             fi | ||||
|           ''} | ||||
| 
 | ||||
|           # Go to the parent folder to make sure that all packages are pinpointed | ||||
|           cd .. | ||||
|           ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} | ||||
| 
 | ||||
|           ${prepareAndInvokeNPM { inherit packageName bypassCache reconstructLock npmFlags production; }} | ||||
| 
 | ||||
|           # Expose the executables that were installed | ||||
|           cd .. | ||||
|           ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} | ||||
| 
 | ||||
|           mv ${packageName} lib | ||||
|           ln -s $out/lib/node_modules/.bin $out/bin | ||||
|         ''; | ||||
|       } // extraArgs); | ||||
| 
 | ||||
|   # Builds a development shell | ||||
|   buildNodeShell = | ||||
|     { name | ||||
|     , packageName | ||||
|     , version | ||||
|     , src | ||||
|     , dependencies ? [] | ||||
|     , buildInputs ? [] | ||||
|     , production ? true | ||||
|     , npmFlags ? "" | ||||
|     , dontNpmInstall ? false | ||||
|     , bypassCache ? false | ||||
|     , reconstructLock ? false | ||||
|     , dontStrip ? true | ||||
|     , unpackPhase ? "true" | ||||
|     , buildPhase ? "true" | ||||
|     , ... }@args: | ||||
| 
 | ||||
|     let | ||||
|       nodeDependencies = buildNodeDependencies args; | ||||
|     in | ||||
|     stdenv.mkDerivation { | ||||
|       name = "node-shell-${name}-${version}"; | ||||
| 
 | ||||
|       buildInputs = [ python nodejs ] ++ lib.optional (stdenv.isLinux) utillinux ++ buildInputs; | ||||
|       buildCommand = '' | ||||
|         mkdir -p $out/bin | ||||
|         cat > $out/bin/shell <<EOF | ||||
|         #! ${stdenv.shell} -e | ||||
|         $shellHook | ||||
|         exec ${stdenv.shell} | ||||
|         EOF | ||||
|         chmod +x $out/bin/shell | ||||
|       ''; | ||||
| 
 | ||||
|       # Provide the dependencies in a development shell through the NODE_PATH environment variable | ||||
|       inherit nodeDependencies; | ||||
|       shellHook = lib.optionalString (dependencies != []) '' | ||||
|         export NODE_PATH=${nodeDependencies}/lib/node_modules | ||||
|         export PATH="${nodeDependencies}/bin:$PATH" | ||||
|       ''; | ||||
|     }; | ||||
| in | ||||
| { | ||||
|   buildNodeSourceDist = lib.makeOverridable buildNodeSourceDist; | ||||
|   buildNodePackage = lib.makeOverridable buildNodePackage; | ||||
|   buildNodeDependencies = lib.makeOverridable buildNodeDependencies; | ||||
|   buildNodeShell = lib.makeOverridable buildNodeShell; | ||||
| } | ||||
							
								
								
									
										4216
									
								
								profiles/helix-zone/node-packages.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4216
									
								
								profiles/helix-zone/node-packages.nix
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										48
									
								
								profiles/helix-zone/pkg-mx-puppet-slack.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								profiles/helix-zone/pkg-mx-puppet-slack.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | |||
| { stdenv, fetchFromGitHub, pkgs, lib, nodejs, nodePackages, pkg-config, libjpeg, pixman, cairo, pango }: | ||||
| 
 | ||||
| let | ||||
|   # No official version ever released | ||||
|   src = fetchFromGitHub { | ||||
|     owner = "Sorunome"; | ||||
|     repo = "mx-puppet-slack"; | ||||
|     rev = "691e53d2d703bd169e1f23a8d8dff3f008d8c4ef"; | ||||
|     sha256 = "1yczhfpa4qzvijcpgc2pr10s009qb6jwlfwpcbb17g2wsx6zj0c2"; | ||||
|   }; | ||||
| 
 | ||||
|   myNodePackages = import ./node-composition.nix { | ||||
|     inherit pkgs nodejs; | ||||
|     inherit (stdenv.hostPlatform) system; | ||||
|   }; | ||||
| 
 | ||||
| in myNodePackages.package.override { | ||||
|   pname = "mx-puppet-slack"; | ||||
| 
 | ||||
|   inherit src; | ||||
| 
 | ||||
|   nativeBuildInputs = [ nodePackages.node-pre-gyp pkg-config ]; | ||||
|   buildInputs = [ libjpeg pixman cairo pango ]; | ||||
| 
 | ||||
|   postInstall = '' | ||||
|     # Patch shebangs in node_modules, otherwise the webpack build fails with interpreter problems | ||||
|     patchShebangs --build "$out/lib/node_modules/mx-puppet-slack/node_modules/" | ||||
|     # compile Typescript sources | ||||
|     npm run build | ||||
| 
 | ||||
|     # Make an executable to run the server | ||||
|     mkdir -p $out/bin | ||||
|     cat <<EOF > $out/bin/mx-puppet-slack | ||||
|     #!/bin/sh | ||||
|     exec ${nodejs}/bin/node $out/lib/node_modules/mx-puppet-slack/build/index.js "\$@" | ||||
|     EOF | ||||
|     chmod +x $out/bin/mx-puppet-slack | ||||
|   ''; | ||||
| 
 | ||||
|   meta = with lib; { | ||||
|     description = "A slack puppeting bridge for matrix"; | ||||
|     license = licenses.asl20; | ||||
|     homepage = "https://github.com/Sorunome/mx-puppet-slack"; | ||||
|     maintainers = with maintainers; [ chickensoupwithrice ]; | ||||
|     platforms = platforms.unix; | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										11
									
								
								profiles/helix-zone/rss-bridge.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								profiles/helix-zone/rss-bridge.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| {pkgs, lib, config, ...}: | ||||
| { | ||||
|   services.rss-bridge = { | ||||
|     enable = true; | ||||
|     virtualHost = "bridge.sealight.xyz"; | ||||
|     whitelist = [ "Facebook" "Bandcamp" "Twitter" "Telegram" "Instagram" "Reddit"]; | ||||
|   }; | ||||
| 
 | ||||
|   services.nginx.virtualHosts."bridge.sealight.xyz".forceSSL = true; | ||||
|   services.nginx.virtualHosts."bridge.sealight.xyz".enableACME = true; | ||||
| } | ||||
							
								
								
									
										14
									
								
								profiles/helix-zone/sealight.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								profiles/helix-zone/sealight.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| { | ||||
|    services.nginx = { | ||||
|       enable = true; | ||||
|       vhost = {  | ||||
| 	  "sealight.xyz" = { | ||||
| 		  forceSSL = true; | ||||
| 		  enableACME = true; | ||||
| 		  locations."/" = { | ||||
| 		    root = "/var/www/sealight.xyz" | ||||
| 		  }; | ||||
|       }; | ||||
|     }; | ||||
|    }; | ||||
| } | ||||
							
								
								
									
										32
									
								
								profiles/helix-zone/wireguard.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								profiles/helix-zone/wireguard.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| { config, pkgs, lib, ... }: | ||||
| {  | ||||
|   environment.systemPackages = [ pkgs.wireguard pkgs.mosh ]; | ||||
|   networking.nat = { | ||||
|       enable = true; | ||||
|       externalInterface = "ens3"; | ||||
|       internalInterfaces = [ "wg0" ]; | ||||
|   }; | ||||
|   networking.firewall = { | ||||
|     allowedUDPPorts = [ 60990 ]; | ||||
|   }; | ||||
| 
 | ||||
|   networking.wireguard.interfaces.wg0 = { | ||||
|     ips = [ "10.0.69.1/24" ]; | ||||
|     listenPort = 60990; | ||||
|     privateKeyFile = "/var/lib/wireguard/priv"; | ||||
|     peers = [ | ||||
|     { # box | ||||
|       publicKey = "Ra78mOc110K7URN5uB3m9d78iBKgeRHzT+3HkiFp9BU="; | ||||
|       allowedIPs = [ "10.0.69.4/32" ]; | ||||
|     } | ||||
|     { # line | ||||
|       publicKey = "fsb1FuGmYi89p4CVXytKw2FYamONKtoanxrgs/dJjC8="; | ||||
|       allowedIPs = [ "10.0.69.3/32" ]; | ||||
|     } | ||||
|     { # curve | ||||
|       publicKey = "XmV4AcPPND/eeSI6d9M1iahCjtymqY6DdUDEFNP/x3g="; | ||||
|       allowedIPs = [ "10.0.69.2/32" ]; | ||||
|     } | ||||
| ]; | ||||
|   }; | ||||
| } | ||||
		Loading…
	
		Reference in a new issue