From c88fae5277651ae9aba44e7384b42a5c879b1e22 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sat, 8 Feb 2025 00:58:07 +0300 Subject: [PATCH] chore: remove whitby configuration Removes whitby DNS records and other related configuration that is no longer required now that whitby is gone. whitby served us well. RIP. This resolves b/433. Change-Id: I56fe6f88cde9112fc3bfc79758ac33e88a743422 Reviewed-on: https://cl.tvl.fyi/c/depot/+/13117 Reviewed-by: sterni Tested-by: BuildkiteCI Autosubmit: tazjin --- default.nix | 10 +- ops/glesys/dns-tvl-fyi.tf | 25 +-- ops/glesys/dns-tvl-su.tf | 14 -- ops/glesys/main.tf | 10 - ops/machines/all-systems.nix | 1 - ops/machines/whitby/OWNERS | 5 - ops/machines/whitby/README.md | 5 - ops/machines/whitby/default.nix | 319 ------------------------------ ops/modules/builderball.nix | 1 - ops/modules/known-hosts.nix | 5 - ops/modules/monitoring.nix | 2 +- ops/modules/monorepo-gerrit.nix | 2 +- ops/modules/www/cache.tvl.fyi.nix | 7 +- ops/nixos.nix | 3 +- ops/pipelines/depot.nix | 2 +- ops/secrets/secrets.nix | 41 ++-- web/panettone/src/panettone.lisp | 2 +- 17 files changed, 37 insertions(+), 417 deletions(-) delete mode 100644 ops/machines/whitby/OWNERS delete mode 100644 ops/machines/whitby/README.md delete mode 100644 ops/machines/whitby/default.nix diff --git a/default.nix b/default.nix index d7623eeee..caeab3519 100644 --- a/default.nix +++ b/default.nix @@ -27,13 +27,12 @@ let ''; exceptions = [ - # whitby is allowed to access //users for several reasons: + # machines is allowed to access //users for several reasons: # # 1. User SSH keys are set in //users. - # 2. Some personal websites or demo projects are served from it. + # 2. Some personal websites or demo projects are served from there. [ "ops" "machines" "bugry" ] [ "ops" "machines" "nevsky" ] - [ "ops" "machines" "whitby" ] # Due to evaluation order this also affects these targets. # TODO(tazjin): Can this one be removed somehow? @@ -51,9 +50,8 @@ let ''; exceptions = [ - # For the same reason as above, whitby is exempt to serve the - # corp website. - [ "ops" "machines" "whitby" ] + # For the same reason as above, machines are exempt to serve the corp + # website. [ "ops" "nixos" ] [ "ops" "machines" "all-systems" ] ]; diff --git a/ops/glesys/dns-tvl-fyi.tf b/ops/glesys/dns-tvl-fyi.tf index 233cb758e..837f40aed 100644 --- a/ops/glesys/dns-tvl-fyi.tf +++ b/ops/glesys/dns-tvl-fyi.tf @@ -39,20 +39,6 @@ resource "glesys_dnsdomain_record" "tvl_fyi_apex_AAAA" { data = var.bugry_ipv6 } -resource "glesys_dnsdomain_record" "tvl_fyi_whitby_A" { - domain = glesys_dnsdomain.tvl_fyi.id - host = "whitby" - type = "A" - data = var.whitby_ipv4 -} - -resource "glesys_dnsdomain_record" "tvl_fyi_whitby_AAAA" { - domain = glesys_dnsdomain.tvl_fyi.id - host = "whitby" - type = "AAAA" - data = var.whitby_ipv6 -} - resource "glesys_dnsdomain_record" "tvl_fyi_nevsky_A" { domain = glesys_dnsdomain.tvl_fyi.id host = "nevsky" @@ -113,7 +99,7 @@ resource "glesys_dnsdomain_record" "cache_tvl_fyi_A" { host = "cache" type = "A" data = each.key - for_each = toset([var.whitby_ipv4, var.nevsky_ipv4]) + for_each = toset([var.nevsky_ipv4]) } resource "glesys_dnsdomain_record" "cache_tvl_fyi_AAAA" { @@ -121,18 +107,11 @@ resource "glesys_dnsdomain_record" "cache_tvl_fyi_AAAA" { host = "cache" type = "AAAA" data = each.key - for_each = toset([var.whitby_ipv6, var.nevsky_ipv6]) + for_each = toset([var.nevsky_ipv6]) } # Builderball cache records -resource "glesys_dnsdomain_record" "tvl_fyi_cache_whitby_CNAME" { - domain = glesys_dnsdomain.tvl_fyi.id - type = "CNAME" - data = "whitby.tvl.fyi." - host = "whitby.cache" -} - resource "glesys_dnsdomain_record" "tvl_fyi_cache_nevsky_CNAME" { domain = glesys_dnsdomain.tvl_fyi.id type = "CNAME" diff --git a/ops/glesys/dns-tvl-su.tf b/ops/glesys/dns-tvl-su.tf index 0e655c904..df5685893 100644 --- a/ops/glesys/dns-tvl-su.tf +++ b/ops/glesys/dns-tvl-su.tf @@ -39,20 +39,6 @@ resource "glesys_dnsdomain_record" "tvl_su_apex_AAAA" { data = var.bugry_ipv6 } -resource "glesys_dnsdomain_record" "tvl_su_whitby_A" { - domain = glesys_dnsdomain.tvl_su.id - host = "whitby" - type = "A" - data = var.whitby_ipv4 -} - -resource "glesys_dnsdomain_record" "tvl_su_whitby_AAAA" { - domain = glesys_dnsdomain.tvl_su.id - host = "whitby" - type = "AAAA" - data = var.whitby_ipv6 -} - resource "glesys_dnsdomain_record" "tvl_su_sanduny_A" { domain = glesys_dnsdomain.tvl_su.id host = "sanduny" diff --git a/ops/glesys/main.tf b/ops/glesys/main.tf index ebb58cb37..3c566376b 100644 --- a/ops/glesys/main.tf +++ b/ops/glesys/main.tf @@ -51,16 +51,6 @@ resource "glesys_objectstorage_credential" "litestream" { description = "key for litestream" } -variable "whitby_ipv4" { - type = string - default = "49.12.129.211" -} - -variable "whitby_ipv6" { - type = string - default = "2a01:4f8:242:5b21:0:feed:edef:beef" -} - variable "nevsky_ipv4" { type = string default = "188.225.81.75" diff --git a/ops/machines/all-systems.nix b/ops/machines/all-systems.nix index fd31dfa25..c8a325a1c 100644 --- a/ops/machines/all-systems.nix +++ b/ops/machines/all-systems.nix @@ -2,7 +2,6 @@ (with depot.ops.machines; [ sanduny - whitby bugry nevsky ]) ++ diff --git a/ops/machines/whitby/OWNERS b/ops/machines/whitby/OWNERS deleted file mode 100644 index 4581a80d6..000000000 --- a/ops/machines/whitby/OWNERS +++ /dev/null @@ -1,5 +0,0 @@ -set noparent - -# Want in on this list? Try paying! -lukegb -tazjin diff --git a/ops/machines/whitby/README.md b/ops/machines/whitby/README.md deleted file mode 100644 index 55287c541..000000000 --- a/ops/machines/whitby/README.md +++ /dev/null @@ -1,5 +0,0 @@ -whitby -====== - -`whitby.tvl.fyi` is our dedicated server providing continuous -integration services and other random nonsense. diff --git a/ops/machines/whitby/default.nix b/ops/machines/whitby/default.nix deleted file mode 100644 index c2e1044ff..000000000 --- a/ops/machines/whitby/default.nix +++ /dev/null @@ -1,319 +0,0 @@ -{ depot, lib, pkgs, ... }: # readTree options -{ config, ... }: # passed by module system - -let - inherit (builtins) listToAttrs; - inherit (lib) range; - - mod = name: depot.path.origSrc + ("/ops/modules/" + name); -in -{ - imports = [ - (mod "builderball.nix") - (mod "harmonia.nix") - (mod "journaldriver.nix") - (mod "tvl-buildkite.nix") - (mod "tvl-users.nix") - (mod "www/cache.tvl.fyi.nix") - (mod "www/cache.tvl.su.nix") - (mod "www/self-cache.tvl.fyi.nix") - (mod "www/self-redirect.nix") - (mod "www/wigglydonke.rs.nix") - - (depot.third_party.agenix.src + "/modules/age.nix") - ]; - - hardware = { - enableRedistributableFirmware = true; - cpu.amd.updateMicrocode = true; - }; - - boot = { - tmp.useTmpfs = true; - kernelModules = [ "kvm-amd" ]; - supportedFilesystems = [ "zfs" ]; - - initrd = { - availableKernelModules = [ - "igb" - "xhci_pci" - "nvme" - "ahci" - "usbhid" - "usb_storage" - "sr_mod" - ]; - - # Enable SSH in the initrd so that we can enter disk encryption - # passwords remotely. - network = { - enable = true; - ssh = { - enable = true; - port = 2222; - authorizedKeys = - depot.users.tazjin.keys.all - ++ depot.users.lukegb.keys.all - ++ [ depot.users.aspen.keys.whitby ]; - - hostKeys = [ - /etc/secrets/initrd_host_ed25519_key - ]; - }; - - # this will launch the zfs password prompt on login and kill the - # other prompt - postCommands = '' - echo "zfs load-key -a && killall zfs" >> /root/.profile - ''; - }; - }; - - kernel.sysctl = { - "net.ipv4.tcp_congestion_control" = "bbr"; - }; - - loader.grub = { - enable = true; - efiSupport = true; - efiInstallAsRemovable = true; - device = "/dev/disk/by-id/nvme-SAMSUNG_MZQLB1T9HAJR-00007_S439NA0N201620"; - }; - - zfs.requestEncryptionCredentials = true; - }; - - fileSystems = { - "/" = { - device = "zroot/root"; - fsType = "zfs"; - }; - - "/boot" = { - device = "/dev/disk/by-uuid/073E-7FBD"; - fsType = "vfat"; - }; - - "/nix" = { - device = "zroot/nix"; - fsType = "zfs"; - }; - - "/home" = { - device = "zroot/home"; - fsType = "zfs"; - }; - }; - - networking = { - # Glass is boring, but Luke doesn't like Wapping - the Prospect of - # Whitby, however, is quite a pleasant establishment. - hostName = "whitby"; - domain = "tvl.fyi"; - hostId = "b38ca543"; - useDHCP = false; - - # Don't use Hetzner's DNS servers. - nameservers = [ - "8.8.8.8" - "8.8.4.4" - ]; - - defaultGateway6 = { - address = "fe80::1"; - interface = "enp196s0"; - }; - - firewall.allowedTCPPorts = [ 22 80 443 4238 8443 29418 ]; - firewall.allowedUDPPorts = [ 8443 ]; - - interfaces.enp196s0.useDHCP = true; - interfaces.enp196s0.ipv6.addresses = [ - { - address = "2a01:04f8:0242:5b21::feed:edef:beef"; - prefixLength = 64; - } - ]; - }; - - # Generate an immutable /etc/resolv.conf from the nameserver settings - # above (otherwise DHCP overwrites it): - environment.etc."resolv.conf" = with lib; { - source = pkgs.writeText "resolv.conf" '' - ${concatStringsSep "\n" (map (ns: "nameserver ${ns}") config.networking.nameservers)} - options edns0 - ''; - }; - - # Disable background git gc system-wide, as it has a tendency to break CI. - environment.etc."gitconfig".source = pkgs.writeText "gitconfig" '' - [gc] - autoDetach = false - ''; - - time.timeZone = "UTC"; - - nix = { - nrBuildUsers = 256; - settings = { - max-jobs = lib.mkDefault 64; - secret-key-files = "/run/agenix/nix-cache-priv"; - - trusted-users = [ - "aspen" - "lukegb" - "tazjin" - "sterni" - ]; - }; - - sshServe = { - enable = true; - keys = with depot.users; - tazjin.keys.all - ++ lukegb.keys.all - ++ [ aspen.keys.whitby ] - ++ sterni.keys.all - ; - }; - }; - - programs.mtr.enable = true; - programs.mosh.enable = true; - services.openssh = { - enable = true; - settings = { - PasswordAuthentication = false; - KbdInteractiveAuthentication = false; - }; - }; - - # Configure secrets for services that need them. - age.secrets = - let - secretFile = name: depot.ops.secrets."${name}.age"; - in - { - clbot.file = secretFile "clbot"; - gerrit-autosubmit.file = secretFile "gerrit-autosubmit"; - grafana.file = secretFile "grafana"; - irccat.file = secretFile "irccat"; - keycloak-db.file = secretFile "keycloak-db"; - owothia.file = secretFile "owothia"; - panettone.file = secretFile "panettone"; - smtprelay.file = secretFile "smtprelay"; - teleirc.file = secretFile "teleirc"; - - nix-cache-priv = { - file = secretFile "nix-cache-priv"; - mode = "0440"; - group = "harmonia"; - }; - - buildkite-agent-token = { - file = secretFile "buildkite-agent-token"; - mode = "0440"; - group = "buildkite-agents"; - }; - - buildkite-graphql-token = { - file = secretFile "buildkite-graphql-token"; - mode = "0440"; - group = "buildkite-agents"; - }; - - buildkite-besadii-config = { - file = secretFile "besadii"; - mode = "0440"; - group = "buildkite-agents"; - }; - - buildkite-private-key = { - file = secretFile "buildkite-ssh-private-key"; - mode = "0440"; - group = "buildkite-agents"; - }; - - gerrit-besadii-config = { - file = secretFile "besadii"; - owner = "git"; - }; - - gerrit-secrets = { - file = secretFile "gerrit-secrets"; - path = "/var/lib/gerrit/etc/secure.config"; - owner = "git"; - mode = "0400"; - }; - - clbot-ssh = { - file = secretFile "clbot-ssh"; - owner = "clbot"; - }; - - # Not actually a secret - nix-cache-pub = { - file = secretFile "nix-cache-pub"; - mode = "0444"; - }; - - depot-replica-key = { - file = secretFile "depot-replica-key"; - mode = "0500"; - owner = "git"; - group = "git"; - path = "/var/lib/git/.ssh/id_ed25519"; - }; - }; - - # Automatically collect garbage from the Nix store. - services.depot.automatic-gc = { - enable = true; - interval = "1 hour"; - diskThreshold = 200; # GiB - maxFreed = 420; # GiB - preserveGenerations = "90d"; - }; - - # Run a handful of Buildkite agents to support parallel builds. - services.depot.buildkite = { - enable = true; - agentCount = 32; - }; - - # Run Nix cache proxy - services.depot.builderball.enable = true; - - # Run a Harmonia binary cache. - # - # TODO(tazjin): switch to upstream module after fix for Nix 2.3 - services.depot.harmonia = { - enable = true; - signKeyPaths = [ (config.age.secretsDir + "/nix-cache-priv") ]; - settings.bind = "127.0.0.1:6443"; - settings.priority = 50; - }; - - services.fail2ban.enable = true; - - # Join TVL Tailscale network at net.tvl.fyi - services.tailscale = { - enable = true; - useRoutingFeatures = "server"; # for exit-node usage - }; - - security.sudo.extraRules = [ - { - groups = [ "wheel" ]; - commands = [{ command = "ALL"; options = [ "NOPASSWD" ]; }]; - } - ]; - - zramSwap.enable = true; - - # Use TVL cache locally through the proxy; for cross-builder substitution. - tvl.cache.enable = true; - tvl.cache.builderball = true; - - system.stateVersion = "20.03"; -} diff --git a/ops/modules/builderball.nix b/ops/modules/builderball.nix index d56c69513..9c416affc 100644 --- a/ops/modules/builderball.nix +++ b/ops/modules/builderball.nix @@ -18,7 +18,6 @@ in description = "Public addresses of caches to use"; default = [ - "whitby.cache.tvl.fyi" "nevsky.cache.tvl.fyi" ]; }; diff --git a/ops/modules/known-hosts.nix b/ops/modules/known-hosts.nix index 16269dae0..93f0ca75e 100644 --- a/ops/modules/known-hosts.nix +++ b/ops/modules/known-hosts.nix @@ -3,11 +3,6 @@ { programs.ssh.knownHosts = { - whitby = { - hostNames = [ "whitby.tvl.fyi" "whitby.tvl.su" ]; - publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILNh/w4BSKov0jdz3gKBc98tpoLta5bb87fQXWBhAl2I"; - }; - sanduny = { hostNames = [ "sanduny.tvl.su" ]; publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOag0XhylaTVhmT6HB8EN2Fv5Ymrc4ZfypOXONUkykTX"; diff --git a/ops/modules/monitoring.nix b/ops/modules/monitoring.nix index 654f8d87e..7a186df31 100644 --- a/ops/modules/monitoring.nix +++ b/ops/modules/monitoring.nix @@ -25,7 +25,7 @@ nginx = { enable = true; sslVerify = false; - constLabels = [ "host=whitby" ]; + constLabels = [ "host=${config.networking.hostName}" ]; }; }; diff --git a/ops/modules/monorepo-gerrit.nix b/ops/modules/monorepo-gerrit.nix index dd57a57b8..5c8c8e841 100644 --- a/ops/modules/monorepo-gerrit.nix +++ b/ops/modules/monorepo-gerrit.nix @@ -4,7 +4,7 @@ let cfg = config.services.gerrit; - besadiiWithConfig = name: pkgs.writeShellScript "besadii-whitby" '' + besadiiWithConfig = name: pkgs.writeShellScript "besadii-hook" '' export BESADII_CONFIG=/run/agenix/gerrit-besadii-config exec -a ${name} ${depot.ops.besadii}/bin/besadii "$@" ''; diff --git a/ops/modules/www/cache.tvl.fyi.nix b/ops/modules/www/cache.tvl.fyi.nix index b0c90267a..88f8131c4 100644 --- a/ops/modules/www/cache.tvl.fyi.nix +++ b/ops/modules/www/cache.tvl.fyi.nix @@ -6,6 +6,9 @@ let # This attrset forms a linked list of hosts, which delegate ACME fallbacks to # each other. These *must* form a circle, otherwise we may end up walking only # part of the ring. + # + # TODO: remove whitby from here, it is gone; leaving this code for now for + # easier discovery when reconfiguring this. acmeFallback = host: ({ whitby = "nevsky.cache.tvl.fyi"; nevsky = "whitby.cache.tvl.fyi"; # GOTO 1 @@ -26,7 +29,9 @@ in # hosts. This config is kind of messy; it would be nice to generate a # correct ring from the depot fixpoint, but this may be impossible due to # infinite recursion. Please read the comment on `acmeFallback` above. - acmeFallbackHost = acmeFallback config.networking.hostName; + # + # TODO: whitby is gone, this is not needed at the moment + # acmeFallbackHost = acmeFallback config.networking.hostName; extraConfig = '' location = /cache-key.pub { diff --git a/ops/nixos.nix b/ops/nixos.nix index b75b5efac..de649711f 100644 --- a/ops/nixos.nix +++ b/ops/nixos.nix @@ -60,9 +60,8 @@ in rec { ''; # Systems that should be built in CI - whitbySystem = (nixosFor depot.ops.machines.whitby).system; sandunySystem = (nixosFor depot.ops.machines.sanduny).system; bugrySystem = (nixosFor depot.ops.machines.bugry).system; nevskySystem = (nixosFor depot.ops.machines.nevsky).system; - meta.ci.targets = [ "sandunySystem" "whitbySystem" "bugrySystem" "nevskySystem" ]; + meta.ci.targets = [ "sandunySystem" "bugrySystem" "nevskySystem" ]; } diff --git a/ops/pipelines/depot.nix b/ops/pipelines/depot.nix index 18cb8a709..f88250360 100644 --- a/ops/pipelines/depot.nix +++ b/ops/pipelines/depot.nix @@ -28,7 +28,7 @@ let nix-build -A ci.gcroot --out-link /nix/var/nix/gcroots/depot/canon ''; - # Ensure that anchoring happens on whitby, so that cache.tvl.su always + # Ensure that anchoring happens on nevsky, so that cache.tvl.su always # has the full cache. Unanchored machines may garbage collect live # paths. agents.hostname = "nevsky"; diff --git a/ops/secrets/secrets.nix b/ops/secrets/secrets.nix index f1b3c0555..273f00d62 100644 --- a/ops/secrets/secrets.nix +++ b/ops/secrets/secrets.nix @@ -24,44 +24,43 @@ let flokli = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPTVTXOutUZZjXLB0lUSgeKcSY/8mxKkC0ingGK1whD2 flokli"; sanduny = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOag0XhylaTVhmT6HB8EN2Fv5Ymrc4ZfypOXONUkykTX"; - whitby = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILNh/w4BSKov0jdz3gKBc98tpoLta5bb87fQXWBhAl2I"; nevsky = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHQe7M+G8Id3ZD7j+I07TCUV1o12q1vpsOXHRlcPSEfa"; bugry = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGqG6sITyJ/UsQ/RtYqmmMvTT4r4sppadoQIz5SvA+5J"; admins = tazjin ++ aspen ++ sterni; - allHosts = [ whitby sanduny nevsky bugry ]; + allHosts = [ sanduny nevsky bugry ]; for = hosts: { publicKeys = hosts ++ admins; }; in { - "besadii.age" = for [ whitby nevsky ]; - "buildkite-agent-token.age" = for [ whitby nevsky ]; - "buildkite-graphql-token.age" = for [ whitby nevsky ]; - "buildkite-ssh-private-key.age" = for [ whitby nevsky ]; - "clbot-ssh.age" = for [ whitby nevsky ]; - "clbot.age" = for [ whitby nevsky ]; + "besadii.age" = for [ nevsky ]; + "buildkite-agent-token.age" = for [ nevsky ]; + "buildkite-graphql-token.age" = for [ nevsky ]; + "buildkite-ssh-private-key.age" = for [ nevsky ]; + "clbot-ssh.age" = for [ nevsky ]; + "clbot.age" = for [ nevsky ]; "depot-inbox-imap.age" = for [ sanduny ]; - "depot-replica-key.age" = for [ whitby nevsky ]; - "gerrit-autosubmit.age" = for [ whitby nevsky ]; - "gerrit-secrets.age" = for [ whitby nevsky ]; - "grafana.age" = for [ whitby nevsky ]; - "irccat.age" = for [ whitby nevsky ]; + "depot-replica-key.age" = for [ nevsky ]; + "gerrit-autosubmit.age" = for [ nevsky ]; + "gerrit-secrets.age" = for [ nevsky ]; + "grafana.age" = for [ nevsky ]; + "irccat.age" = for [ nevsky ]; "journaldriver.age" = for allHosts; - "keycloak-db.age" = for [ whitby nevsky ]; - "nix-cache-priv.age" = for [ whitby nevsky ]; - "nix-cache-pub.age" = for [ whitby nevsky ]; - "owothia.age" = for [ whitby nevsky ]; - "panettone.age" = for [ whitby nevsky ]; + "keycloak-db.age" = for [ nevsky ]; + "nix-cache-priv.age" = for [ nevsky ]; + "nix-cache-pub.age" = for [ nevsky ]; + "owothia.age" = for [ nevsky ]; + "panettone.age" = for [ nevsky ]; "restic-bugry.age" = for [ bugry ]; "restic-nevsky.age" = for [ nevsky ]; "restic-sanduny.age" = for [ sanduny ]; - "smtprelay.age" = for [ whitby nevsky ]; - "teleirc.age" = for [ whitby nevsky ]; + "smtprelay.age" = for [ nevsky ]; + "teleirc.age" = for [ nevsky ]; "tf-buildkite.age" = for [ /* humans only */ ]; "tf-glesys.age" = for [ /* humans only */ ]; "tf-keycloak.age" = for [ flokli ]; - "tvl-alerts-bot-telegram-token.age" = for [ whitby nevsky ]; + "tvl-alerts-bot-telegram-token.age" = for [ nevsky ]; "wg-bugry.age" = for [ bugry ]; "wg-nevsky.age" = for [ nevsky ]; "yc-restic.age" = for [ nevsky sanduny bugry ]; diff --git a/web/panettone/src/panettone.lisp b/web/panettone/src/panettone.lisp index 37d194d0f..5396abe59 100644 --- a/web/panettone/src/panettone.lisp +++ b/web/panettone/src/panettone.lisp @@ -675,7 +675,7 @@ given subject an body (in a thread, to avoid blocking)" (comment (setq hunchentoot:*catch-errors-p* nil) ;; to setup an ssh tunnel to cheddar+irccat for development: - ;; ssh -N -L 4238:localhost:4238 -L 4722:localhost:4722 whitby.tvl.fyi + ;; ssh -N -L 4238:localhost:4238 -L 4722:localhost:4722 nevsky.tvl.fyi (start-panettone :port 6161 :session-secret "session-secret") )