From e838ef675f700623e576a452775f5a8ca107293c Mon Sep 17 00:00:00 2001 From: Anirudh Oppiliappan Date: Mon, 3 Nov 2025 10:46:26 +0200 Subject: [PATCH] nixify appview Change-Id: oqkkllmzurupzntnlmvvwryxntqtmttz Signed-off-by: Anirudh Oppiliappan --- flake.lock | 8 +-- flake.nix | 30 +++++++++ hosts/appview/configuration.nix | 57 ++++++++++++++++ hosts/appview/disk-config.nix | 56 ++++++++++++++++ hosts/appview/services/appview.nix | 11 +++ hosts/appview/services/nginx-alpha.nix | 53 +++++++++++++++ hosts/appview/services/nginx.nix | 93 ++++++++++++++++++++++++++ hosts/nixery/configuration.nix | 2 +- 8 files changed, 305 insertions(+), 5 deletions(-) create mode 100644 hosts/appview/configuration.nix create mode 100644 hosts/appview/disk-config.nix create mode 100644 hosts/appview/services/appview.nix create mode 100644 hosts/appview/services/nginx-alpha.nix create mode 100644 hosts/appview/services/nginx.nix diff --git a/flake.lock b/flake.lock index b4b7b9b..f349dce 100644 --- a/flake.lock +++ b/flake.lock @@ -337,11 +337,11 @@ "sqlite-lib-src": "sqlite-lib-src" }, "locked": { - "lastModified": 1758898964, - "narHash": "sha256-UFCO4KN7EzT058WcJtjiQiIaoKwSP2ddkhPK74S8zug=", + "lastModified": 1762506184, + "narHash": "sha256-4NqqrAHQXMUasM5Vw7BUUgjvXA1xrfYkhaKu6YNxFpo=", "ref": "refs/heads/master", - "rev": "7ddfed41ed0e2241dbb2edb9b0f69fce7e40f820", - "revCount": 1450, + "rev": "30d281f77d830b1c45104a44c9e7e5eafb52b354", + "revCount": 1611, "type": "git", "url": "https://tangled.org/@tangled.org/core" }, diff --git a/flake.nix b/flake.nix index 21a8fba..c41012b 100644 --- a/flake.nix +++ b/flake.nix @@ -29,11 +29,24 @@ }; nixosConfigurations.pds = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; + specialArgs = { + commonArgs = import ./common/ssh.nix; + }; modules = [ disko.nixosModules.disko ./hosts/pds/configuration.nix ]; }; + nixosConfigurations.appview = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + specialArgs = { + commonArgs = import ./common/ssh.nix; + }; + modules = [ + disko.nixosModules.disko + ./hosts/appview/configuration.nix + ]; + }; colmenaHive = colmena.lib.makeHive { meta = { @@ -51,6 +64,23 @@ pkgs.curl ]; }; + appview = { pkgs, ... }: { + deployment = { + targetHost = "alpha.tangled.sh"; + targetPort = 22; + targetUser = "tangler"; + buildOnTarget = true; + }; + nixpkgs.system = "x86_64-linux"; + imports = [ + disko.nixosModules.disko + tangled.nixosModules.appview + ./hosts/appview/configuration.nix + ./hosts/appview/services/appview.nix + ./hosts/appview/services/nginx-alpha.nix + ]; + time.timeZone = "Europe/Helsinki"; + }; pds = { pkgs, ... }: { deployment = { targetHost = "tngl.sh"; diff --git a/hosts/appview/configuration.nix b/hosts/appview/configuration.nix new file mode 100644 index 0000000..e890b14 --- /dev/null +++ b/hosts/appview/configuration.nix @@ -0,0 +1,57 @@ +{ modulesPath +, lib +, pkgs +, ... +} @ args: +{ + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + (modulesPath + "/profiles/qemu-guest.nix") + ./disk-config.nix + ]; + boot.loader.grub = { + # no need to set devices, disko will add all devices that have a EF02 partition to the list already + # devices = [ ]; + efiSupport = true; + efiInstallAsRemovable = true; + }; + + networking.hostName = "appview-arn"; + services = { + openssh.enable = true; + }; + + + nix = { + extraOptions = '' + experimental-features = nix-command flakes ca-derivations + warn-dirty = false + keep-outputs = false + ''; + }; + + environment.systemPackages = map lib.lowPrio [ + pkgs.curl + pkgs.gitMinimal + ]; + + users.users.tangler = { + extraGroups = [ "networkmanager" "wheel" ]; + openssh.authorizedKeys.keys = args.commonArgs.sshKeys; + isNormalUser = true; + }; + + security.sudo.extraRules = [ + { + users = [ "tangler" ]; + commands = [ + { + command = "ALL"; + options = [ "NOPASSWD" ]; + } + ]; + } + ]; + + system.stateVersion = "25.05"; +} diff --git a/hosts/appview/disk-config.nix b/hosts/appview/disk-config.nix new file mode 100644 index 0000000..88e17e5 --- /dev/null +++ b/hosts/appview/disk-config.nix @@ -0,0 +1,56 @@ +# Example to create a bios compatible gpt partition +{ lib, ... }: +{ + disko.devices = { + disk.disk1 = { + device = lib.mkDefault "/dev/vda"; + type = "disk"; + content = { + type = "gpt"; + partitions = { + boot = { + name = "boot"; + size = "1M"; + type = "EF02"; + }; + esp = { + name = "ESP"; + size = "500M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + root = { + name = "root"; + size = "100%"; + content = { + type = "lvm_pv"; + vg = "pool"; + }; + }; + }; + }; + }; + lvm_vg = { + pool = { + type = "lvm_vg"; + lvs = { + root = { + size = "100%FREE"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/"; + mountOptions = [ + "defaults" + ]; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/appview/services/appview.nix b/hosts/appview/services/appview.nix new file mode 100644 index 0000000..9ed316c --- /dev/null +++ b/hosts/appview/services/appview.nix @@ -0,0 +1,11 @@ +{ modulesPath +, lib +, pkgs +, ... +} @ args: +{ + services.tangled.appview = { + enable = true; + environmentFile = "/etc/secrets/appview.env"; + }; +} diff --git a/hosts/appview/services/nginx-alpha.nix b/hosts/appview/services/nginx-alpha.nix new file mode 100644 index 0000000..5370f99 --- /dev/null +++ b/hosts/appview/services/nginx-alpha.nix @@ -0,0 +1,53 @@ +{ config, pkgs, ... }: +{ + services.nginx = { + enable = true; + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + + # Fix proxy headers hash warnings + appendHttpConfig = '' + proxy_headers_hash_max_size 1024; + proxy_headers_hash_bucket_size 128; + ''; + + virtualHosts = { + # AppView service on alpha.tangled.sh + "alpha.tangled.sh" = { + forceSSL = true; + enableACME = true; + + locations."/" = { + proxyPass = "http://127.0.0.1:3000"; + extraConfig = '' + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + client_max_body_size 100M; + ''; + }; + + # WebSocket support for /logs endpoint + locations."~ /logs$" = { + proxyPass = "http://127.0.0.1:3000"; + proxyWebsockets = true; + extraConfig = '' + proxy_read_timeout 86400; + ''; + }; + }; + }; + }; + + # Open firewall ports + networking.firewall.allowedTCPPorts = [ 80 443 ]; + + # ACME configuration for Let's Encrypt + security.acme = { + acceptTerms = true; + defaults.email = "team@tangled.org"; + }; +} diff --git a/hosts/appview/services/nginx.nix b/hosts/appview/services/nginx.nix new file mode 100644 index 0000000..dac9732 --- /dev/null +++ b/hosts/appview/services/nginx.nix @@ -0,0 +1,93 @@ +{ config, pkgs, ... }: +{ + services.nginx = { + enable = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + + virtualHosts = { + # Redirect tangled.sh → tangled.org + "tangled.sh" = { + serverAliases = [ "www.tangled.sh" ]; + locations."/" = { + return = "301 https://tangled.org$request_uri"; + }; + forceSSL = true; + enableACME = true; + }; + + # Redirect strings.tangled.sh → tangled.org/strings/* + "strings.tangled.sh" = { + locations."/" = { + return = "301 https://tangled.org/strings$request_uri"; + }; + forceSSL = true; + enableACME = true; + }; + + # Redirect strings.tangled.org → tangled.org/strings/* + "strings.tangled.org" = { + locations."/" = { + return = "301 https://tangled.org/strings$request_uri"; + }; + forceSSL = true; + enableACME = true; + }; + + # Main app on tangled.org + "tangled.org" = { + serverAliases = [ "www.tangled.org" ]; + + forceSSL = true; + enableACME = true; + + extraConfig = '' + # Redirect www → bare domain + if ($host = www.tangled.org) { + return 301 https://tangled.org$request_uri; + } + + client_max_body_size 100M; + ''; + + locations."~ ^/@tangled\\.sh(/.*)?$" = { + return = "301 https://tangled.org/@tangled.org$1$is_args$args"; + }; + + locations."~ ^/tangled\\.sh(/.*)?$" = { + return = "301 https://tangled.org/tangled.org$1$is_args$args"; + }; + + locations."~ /logs$" = { + proxyPass = "http://127.0.0.1:3000"; + proxyWebsockets = true; + extraConfig = '' + proxy_read_timeout 86400; + ''; + }; + + locations."/" = { + proxyPass = "http://127.0.0.1:3000"; + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + include ${config.services.nginx.package}/conf/mime.types; + ''; + }; + }; + }; + }; + + # Open firewall ports + networking.firewall.allowedTCPPorts = [ 80 443 ]; + + # ACME configuration for Let's Encrypt + security.acme = { + acceptTerms = true; + defaults.email = "team@tangled.org"; + }; +} diff --git a/hosts/nixery/configuration.nix b/hosts/nixery/configuration.nix index 04f663d..aad7c07 100644 --- a/hosts/nixery/configuration.nix +++ b/hosts/nixery/configuration.nix @@ -19,7 +19,7 @@ networking.hostName = "nixery"; services = { openssh.enable = true; - tangled-spindle = { + tangled.spindle = { enable = true; server = { owner = "did:plc:wshs7t2adsemcrrd4snkeqli"; # @tangled.sh -- 2.43.0