BIT-28 Gate backend startup on migrations

This commit is contained in:
Tobserver Agent 2026-07-27 15:52:57 +07:00 committed by Tobias Ostner
parent 0296280ac9
commit 2015aac8e4
2 changed files with 195 additions and 34 deletions

View file

@ -2,6 +2,8 @@
let
containerName = "bitcoin-pulse-postgres";
databaseUrl = "jdbc:postgresql://127.0.0.1:5432/bitcoin_pulse?tcpKeepAlive=true";
migrationServiceName = "bitcoin-pulse-migrate";
serviceName = "podman-${containerName}";
runtimeDirectory = "/run/${containerName}";
@ -50,18 +52,58 @@ let
${lib.escapeShellArg "${runtimeDirectory}/migration-password"}
'';
};
waitForPostgresql = pkgs.writeShellApplication {
name = "bitcoin-pulse-wait-for-postgresql";
runtimeInputs = [
pkgs.coreutils
pkgs.postgresql_18
];
text = ''
deadline=$((SECONDS + 60))
echo "Waiting up to 60 seconds for PostgreSQL on 127.0.0.1:5432"
while (( SECONDS < deadline )); do
if pg_isready \
--host=127.0.0.1 \
--port=5432 \
--username=bitcoin_pulse_migration \
--dbname=bitcoin_pulse \
--timeout=2 \
--quiet; then
echo "PostgreSQL is accepting connections"
exit 0
fi
sleep 2
done
echo "PostgreSQL did not become ready on 127.0.0.1:5432 within 60 seconds" >&2
pg_isready \
--host=127.0.0.1 \
--port=5432 \
--username=bitcoin_pulse_migration \
--dbname=bitcoin_pulse \
--timeout=2 || true
exit 1
'';
};
in
{
imports = [ bitcoin-pulse.nixosModules.default ];
services.bitcoin-pulse = {
# BIT-28 will enable the production instance after PostgreSQL readiness
# and migrations have been integrated with these credentials.
enable = false;
enable = true;
bindAddress = "127.0.0.1";
port = 3000;
mempool.baseUrl = "http://127.0.0.1:8999";
database = {
url = databaseUrl;
username = "bitcoin_pulse_app";
passwordFile = secretFiles.app;
};
};
users.groups = {
@ -70,20 +112,28 @@ in
bitcoin-pulse-postgres.gid = 400;
};
users.users.bitcoin-pulse-postgres = {
description = "Rootless PostgreSQL container account for Bitcoin Pulse";
isSystemUser = true;
uid = 400;
group = "bitcoin-pulse-postgres";
extraGroups = [
"bitcoin-pulse"
"bitcoin-pulse-migration"
];
home = "/var/lib/bitcoin-pulse-postgres";
homeMode = "0700";
createHome = true;
linger = true;
autoSubUidGidRange = true;
users.users = {
bitcoin-pulse-migration = {
description = "Bitcoin Pulse database migration account";
isSystemUser = true;
group = "bitcoin-pulse-migration";
};
bitcoin-pulse-postgres = {
description = "Rootless PostgreSQL container account for Bitcoin Pulse";
isSystemUser = true;
uid = 400;
group = "bitcoin-pulse-postgres";
extraGroups = [
"bitcoin-pulse"
"bitcoin-pulse-migration"
];
home = "/var/lib/bitcoin-pulse-postgres";
homeMode = "0700";
createHome = true;
linger = true;
autoSubUidGidRange = true;
};
};
sops.secrets = {
@ -151,14 +201,68 @@ in
};
};
systemd.services.${serviceName}.serviceConfig = {
ExecStartPre = lib.mkAfter [ "${prepareSecrets}/bin/bitcoin-pulse-postgresql-prepare-secrets" ];
ExecStartPost = [ "${cleanupSecrets}/bin/bitcoin-pulse-postgresql-cleanup-secrets" ];
ExecStopPost = lib.mkAfter [ "${cleanupSecrets}/bin/bitcoin-pulse-postgresql-cleanup-secrets" ];
RuntimeDirectoryMode = "0700";
RestartSec = "5s";
TimeoutStopSec = lib.mkForce "90s";
UMask = "0077";
systemd.services = {
${serviceName}.serviceConfig = {
ExecStartPre = lib.mkAfter [ "${prepareSecrets}/bin/bitcoin-pulse-postgresql-prepare-secrets" ];
ExecStartPost = [ "${cleanupSecrets}/bin/bitcoin-pulse-postgresql-cleanup-secrets" ];
ExecStopPost = lib.mkAfter [ "${cleanupSecrets}/bin/bitcoin-pulse-postgresql-cleanup-secrets" ];
RuntimeDirectoryMode = "0700";
RestartSec = "5s";
TimeoutStopSec = lib.mkForce "90s";
UMask = "0077";
};
${migrationServiceName} = {
description = "Migrate the Bitcoin Pulse PostgreSQL database";
requires = [ "${serviceName}.service" ];
after = [ "${serviceName}.service" ];
before = [ "bitcoin-pulse.service" ];
environment = {
MIGRATUS_DATABASE_URL = databaseUrl;
MIGRATUS_USERNAME = "bitcoin_pulse_migration";
MIGRATUS_PASSWORD_FILE = secretFiles.migration;
};
serviceConfig = {
Type = "oneshot";
ExecStartPre = [ "${waitForPostgresql}/bin/bitcoin-pulse-wait-for-postgresql" ];
ExecStart = "${config.services.bitcoin-pulse.package}/bin/bitcoin-pulse-migrate migrate";
User = "bitcoin-pulse-migration";
Group = "bitcoin-pulse-migration";
Restart = "no";
TimeoutStartSec = "5min";
AmbientCapabilities = "";
CapabilityBoundingSet = "";
LockPersonality = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
UMask = "0077";
};
};
bitcoin-pulse = {
requires = [ "${migrationServiceName}.service" ];
after = [ "${migrationServiceName}.service" ];
};
};
environment.systemPackages = [ pkgs.postgresql_18 ];