feat(clan): add vps-relay + strip bbbot cloudflared 🚢
Stage 4.5: declare a Hetzner-hosted reverse-proxy VPS as a clan machine. - nixos/hosts/vps-relay.nix: Debian→NixOS cx23 in hel1. Caddy at public 80/443 reverse-proxies navidrome.dannydannydanny.me and bbbot.dannydannydanny.me over ZT to sunken-ship. - nixos/disko-cloud.nix: simple GPT + ext4 root, no LUKS — cloud provider has physical disk anyway and there's no operator at boot. - flake-modules/clan.nix: register vps-relay as an inventory machine, zerotier peer, internet networking target at its clan-generated ZT IPv6, and add vps-relay.clan to clanHostsModule /etc/hosts. - sunken-ship fitness-bot: drop pkgs.cloudflared from PATH + set WEBAPP_URL=https://bbbot.dannydannydanny.me. Paired with the bbbot upstream patch (start.py honors env WEBAPP_URL and skips cloudflared when set) — once the 15-min fitness-bot-pull timer pulls that change, bbbot will stop churning trycloudflare.com URLs. Vars (zerotier identity/ip + sops machine key) generated on sunken-ship because clan's hermetic sandbox on macOS fails to run the zerotier identity generator (same workaround as for data-mesher earlier). VPS install flow: Hetzner-created Debian box, then `clan machines install vps-relay --target-host root@<public-ipv4>` reinstalls to NixOS; subsequent updates go over ZT.
This commit is contained in:
parent
b0c8664f5c
commit
47fc658523
11 changed files with 187 additions and 1 deletions
34
nixos/disko-cloud.nix
Normal file
34
nixos/disko-cloud.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Disko layout for cloud VPS installs (e.g. Hetzner Cloud).
|
||||
# No LUKS — the provider has physical disk access anyway and there's
|
||||
# no operator present at boot to enter a passphrase.
|
||||
{
|
||||
disko.devices = {
|
||||
disk.main = {
|
||||
type = "disk";
|
||||
device = "/dev/sda";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
size = "512M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "fmask=0022" "dmask=0022" ];
|
||||
};
|
||||
};
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "ext4";
|
||||
mountpoint = "/";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -120,6 +120,11 @@
|
|||
# Code: https://github.com/DannyDannyDanny/bigbiggerbiggestbot cloned at /home/danny/tg_fitness_bot
|
||||
# Bot token: ~danny/.secrets/bigbiggerbiggestbot
|
||||
# Deployment: fitness-bot-pull timer below runs every 15 min, git pulls, restarts service on changes.
|
||||
#
|
||||
# Mini App URL is fronted by Caddy on the vps-relay host at
|
||||
# https://bbbot.dannydannydanny.me (VPS → ZeroTier → localhost:8080).
|
||||
# The bot's start.py honors WEBAPP_URL to skip starting its own
|
||||
# cloudflared Quick Tunnel when we've got a stable URL from the VPS.
|
||||
systemd.services.fitness-bot = let
|
||||
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
|
||||
python-telegram-bot
|
||||
|
|
@ -131,7 +136,8 @@
|
|||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pythonEnv pkgs.cloudflared ];
|
||||
path = [ pythonEnv ];
|
||||
environment.WEBAPP_URL = "https://bbbot.dannydannydanny.me";
|
||||
serviceConfig = {
|
||||
WorkingDirectory = "/home/danny/tg_fitness_bot";
|
||||
ExecStart = "${pythonEnv}/bin/python start.py";
|
||||
|
|
|
|||
77
nixos/hosts/vps-relay.nix
Normal file
77
nixos/hosts/vps-relay.nix
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
# Hetzner Cloud VPS — public reverse proxy into the clan.
|
||||
#
|
||||
# Role: terminates public TLS via Caddy + Let's Encrypt, reverse-proxies
|
||||
# each declared subdomain over ZeroTier to the appropriate homelab host.
|
||||
# No navidrome/bbbot data ever hits disk here; this box is a relay.
|
||||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
imports = [ ../disko-cloud.nix ];
|
||||
|
||||
nixpkgs.hostPlatform = "x86_64-linux";
|
||||
|
||||
# Hetzner Cloud boots EFI with systemd-boot.
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
|
||||
# Cloud provisioners add the initial root SSH key via cloud-init or
|
||||
# equivalent; we don't run cloud-init. All config is baked at install.
|
||||
networking.hostName = "vps-relay";
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
time.timeZone = "Europe/Copenhagen";
|
||||
|
||||
# --- User + SSH ------------------------------------------------------
|
||||
users.users.danny = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ];
|
||||
openssh.authorizedKeys.keys = [
|
||||
# Same pubkey used to reach sunken-ship; set at install via clan.
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKW/akfIiVU5o63YrTAJVZhMj7kXfYHOnXDtlpVFW7pf danny@sunken-ship"
|
||||
];
|
||||
};
|
||||
users.users.root.openssh.authorizedKeys.keys =
|
||||
config.users.users.danny.openssh.authorizedKeys.keys;
|
||||
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
KbdInteractiveAuthentication = false;
|
||||
PermitRootLogin = "prohibit-password";
|
||||
};
|
||||
};
|
||||
|
||||
# --- Firewall --------------------------------------------------------
|
||||
# Public: 22 (SSH), 80 + 443 (Caddy).
|
||||
# ZT interface: trusted (set in the clan ZT module).
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowedTCPPorts = [ 22 80 443 ];
|
||||
|
||||
# --- Caddy reverse proxy --------------------------------------------
|
||||
# Subdomains → clan backends over ZeroTier. IPs are sunken-ship's /
|
||||
# phantom-ship's ZT IPv6; brackets required in URLs.
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
email = "powerhouseplayer@gmail.com";
|
||||
# Tell ACME to use Let's Encrypt's production endpoint (Caddy default).
|
||||
virtualHosts = {
|
||||
"navidrome.dannydannydanny.me".extraConfig = ''
|
||||
reverse_proxy http://[fdd5:53a2:de33:d269:6499:93d5:53a2:de33]:4533
|
||||
'';
|
||||
"bbbot.dannydannydanny.me".extraConfig = ''
|
||||
reverse_proxy http://[fdd5:53a2:de33:d269:6499:93d5:53a2:de33]:8080
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# --- Basic tooling ---------------------------------------------------
|
||||
environment.systemPackages = with pkgs; [
|
||||
git
|
||||
htop
|
||||
tcpdump
|
||||
];
|
||||
|
||||
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue