Tobserver/modules/mempool.nix
2026-04-11 11:38:46 +02:00

182 lines
5.2 KiB
Nix

{ config, pkgs, lib, ...}:
{
virtualisation.oci-containers = {
backend = "podman";
containers = {
mempool-db = {
image = "mariadb:11";
autoStart = true;
environment = {
MARIADB_DATABASE = "mempool";
MARIADB_USER = "mempool";
MARIADB_PASSWORD = "mempool";
MARIADB_ROOT_PASSWORD = "root";
};
volumes = [
"/srv/mempool/mysql:/var/lib/mysql"
];
};
mempool-backend = {
image = "mempool/backend:latest";
autoStart = true;
dependsOn = [ "mempool-db" ];
ports = [ "127.0.0.1:8999:8999" ];
extraOptions = [
"--add-host=host.containers.internal:host-gateway"
];
environment = {
MEMPOOL_NETWORK = "mainnet";
MEMPOOL_BACKEND = "electrum";
MEMPOOL_HTTP_PORT = "8999";
ELECTRUM_HOST = "host.containers.internal";
ELECTRUM_PORT = "50001";
ELECTRUM_TLS_ENABLED = "false";
CORE_RPC_HOST = "host.containers.internal";
CORE_RPC_PORT = "8332";
CORE_RPC_COOKIE = "true";
CORE_RPC_COOKIE_PATH = "/bitcoin/.cookie";
DATABASE_ENABLED = "true";
DATABASE_HOST = "mempool-db";
DATABASE_PORT = "3306";
DATABASE_DATABASE = "mempool";
DATABASE_USERNAME = "mempool";
DATABASE_PASSWORD = "mempool";
STATISTICS_ENABLED = "true";
};
volumes = [
"/run/mempool/bitcoind.cookie:/bitcoin/.cookie:ro"
];
};
mempool-frontend = {
image = "mempool/frontend:latest";
autoStart = true;
ports = [ "127.0.0.1:8998:8080" ];
environment = {
NGINX_HOSTNAME = "mempool.tobiasostner.de";
NGINX_PORT = "443";
NGINX_PROTOCOL = "https";
};
};
};
};
systemd.tmpfiles.rules = lib.mkAfter [
"d /run/mempool 0755 root root - -"
];
# Copy cookie once
systemd.services.mempool-cookie = {
description = "Expose bitcoind cookie for mempool-backend";
after = [ "bitcoind-mainnet.service" ];
wants = [ "bitcoind-mainnet.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = pkgs.writeShellScript "mempool-cookie" ''
set -euo pipefail
for i in $(seq 1 60); do
if [ -f /var/lib/bitcoind/.cookie ]; then
install -m 0644 -o root -g root /var/lib/bitcoind/.cookie /run/mempool/bitcoind.cookie
exit 0
fi
sleep 1
done
echo "Cookie not found after 60s" >&2
exit 1
'';
};
};
# Re-run the cookie copy whenever bitcoind rotates the cookie
systemd.paths.mempool-cookie = {
description = "Watch bitcoind cookie and refresh mempool copy";
wantedBy = [ "multi-user.target" ];
pathConfig = {
PathChanged = "/var/lib/bitcoind/.cookie";
};
};
# When the path triggers, it starts the service
systemd.services.mempool-cookie.wantedBy = lib.mkForce [ ];
systemd.paths.mempool-cookie.unitConfig = {
Unit = "mempool-cookie.service";
};
systemd.services.podman-mempool-backend = {
after = [ "mempool-cookie.service" ];
wants = [ "mempool-cookie.service" ];
};
services.nginx = {
appendHttpConfig = ''
limit_req_zone $binary_remote_addr zone=mempool_api:10m rate=60r/m;
limit_conn_zone $binary_remote_addr zone=mempool_ws:10m;
'';
virtualHosts."mempool.tobiasostner.de" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:8998";
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;
'';
};
locations."/api/" = {
proxyPass = "http://127.0.0.1:8999";
extraConfig = ''
limit_req zone=mempool_api burst=30 nodelay;
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;
proxy_connect_timeout 2s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 10s;
'';
};
locations."/api/v1/ws" = {
proxyPass = "http://127.0.0.1:8999/api/v1/ws";
proxyWebsockets = true;
extraConfig = ''
limit_conn mempool_ws 3;
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;
proxy_connect_timeout 2s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 10s;
'';
};
};
};
networking.firewall.interfaces."podman0".allowedTCPPorts = [ 8332 50001 ];
}