bench: Cloud firewall
This commit is contained in:
@@ -135,6 +135,7 @@ Notes:
|
|||||||
- Caches built nostr-bench at _build/bench/nostr-bench and reuses it when valid.
|
- Caches built nostr-bench at _build/bench/nostr-bench and reuses it when valid.
|
||||||
- Auto-tunes Postgres/Redis/app pool sizing from server RAM + CPU for DB-backed targets.
|
- Auto-tunes Postgres/Redis/app pool sizing from server RAM + CPU for DB-backed targets.
|
||||||
- Randomizes target order per run and wipes persisted target data directories on each start.
|
- Randomizes target order per run and wipes persisted target data directories on each start.
|
||||||
|
- Creates a Hetzner Cloud firewall restricting inbound access to benchmark ports from known IPs only.
|
||||||
- Handles Ctrl-C / SIGTERM with best-effort cloud cleanup.
|
- Handles Ctrl-C / SIGTERM with best-effort cloud cleanup.
|
||||||
- Tries nix .#nostrBenchStaticX86_64Musl first; falls back to docker-built portable nostr-bench.
|
- Tries nix .#nostrBenchStaticX86_64Musl first; falls back to docker-built portable nostr-bench.
|
||||||
- If --parrhesia-image is omitted, requires nix locally.
|
- If --parrhesia-image is omitted, requires nix locally.
|
||||||
@@ -1396,6 +1397,8 @@ async function main() {
|
|||||||
|
|
||||||
const createdServers = [];
|
const createdServers = [];
|
||||||
let sshKeyCreated = false;
|
let sshKeyCreated = false;
|
||||||
|
let firewallName = null;
|
||||||
|
let firewallCreated = false;
|
||||||
let cleanupPromise = null;
|
let cleanupPromise = null;
|
||||||
|
|
||||||
const cleanup = async () => {
|
const cleanup = async () => {
|
||||||
@@ -1424,6 +1427,17 @@ async function main() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (firewallCreated) {
|
||||||
|
console.log("[cleanup] deleting firewall...");
|
||||||
|
await runCommand("hcloud", ["firewall", "delete", firewallName])
|
||||||
|
.then(() => {
|
||||||
|
console.log(`[cleanup] deleted firewall: ${firewallName}`);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn(`[cleanup] failed to delete firewall ${firewallName}: ${error.message || error}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (sshKeyCreated) {
|
if (sshKeyCreated) {
|
||||||
console.log("[cleanup] deleting ssh key...");
|
console.log("[cleanup] deleting ssh key...");
|
||||||
await runCommand("hcloud", ["ssh-key", "delete", keyName])
|
await runCommand("hcloud", ["ssh-key", "delete", keyName])
|
||||||
@@ -1530,6 +1544,42 @@ async function main() {
|
|||||||
...clientInfos.map((client) => waitForSsh(client.ip, keyPath)),
|
...clientInfos.map((client) => waitForSsh(client.ip, keyPath)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Detect orchestrator public IP from the server's perspective.
|
||||||
|
const orchestratorIp = (
|
||||||
|
await sshExec(serverIp, keyPath, "echo $SSH_CLIENT")
|
||||||
|
).stdout.trim().split(/\s+/)[0];
|
||||||
|
|
||||||
|
// Create a firewall restricting inbound access to known benchmark IPs only.
|
||||||
|
firewallName = `${runId}-fw`;
|
||||||
|
const allBenchIps = [orchestratorIp, serverIp, ...clientInfos.map((c) => c.ip)];
|
||||||
|
const sourceIps = [...new Set(allBenchIps)].map((ip) => `${ip}/32`);
|
||||||
|
|
||||||
|
const firewallRules = [
|
||||||
|
{ direction: "in", protocol: "tcp", port: "22", source_ips: sourceIps, description: "SSH" },
|
||||||
|
{ direction: "in", protocol: "tcp", port: "3355", source_ips: sourceIps, description: "Haven" },
|
||||||
|
{ direction: "in", protocol: "tcp", port: "4413", source_ips: sourceIps, description: "Parrhesia" },
|
||||||
|
{ direction: "in", protocol: "tcp", port: "7777", source_ips: sourceIps, description: "strfry" },
|
||||||
|
{ direction: "in", protocol: "tcp", port: "8008", source_ips: sourceIps, description: "Nostream" },
|
||||||
|
{ direction: "in", protocol: "tcp", port: "8080", source_ips: sourceIps, description: "nostr-rs-relay" },
|
||||||
|
{ direction: "in", protocol: "tcp", port: "9090", source_ips: sourceIps, description: "Prometheus" },
|
||||||
|
{ direction: "in", protocol: "tcp", port: "9100", source_ips: sourceIps, description: "node_exporter" },
|
||||||
|
{ direction: "in", protocol: "icmp", source_ips: ["0.0.0.0/0", "::/0"], description: "ICMP" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const rulesPath = path.join(tmpDir, "firewall-rules.json");
|
||||||
|
fs.writeFileSync(rulesPath, JSON.stringify(firewallRules));
|
||||||
|
|
||||||
|
await runCommand("hcloud", ["firewall", "create", "--name", firewallName, "--rules-file", rulesPath]);
|
||||||
|
firewallCreated = true;
|
||||||
|
|
||||||
|
for (const name of createdServers) {
|
||||||
|
await runCommand("hcloud", [
|
||||||
|
"firewall", "apply-to-resource", firewallName,
|
||||||
|
"--type", "server", "--server", name,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
console.log(`[firewall] ${firewallName} applied (sources: ${sourceIps.join(", ")})`);
|
||||||
|
|
||||||
console.log("[phase] install runtime dependencies on server node");
|
console.log("[phase] install runtime dependencies on server node");
|
||||||
const serverInstallCmd = [
|
const serverInstallCmd = [
|
||||||
"set -euo pipefail",
|
"set -euo pipefail",
|
||||||
|
|||||||
Reference in New Issue
Block a user