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