forked from bitcoinafterlife/bal-server
chore: unify DB env vars and harden local Postgres startup
- Use BAL_SERVER_DB_* / BAL_SERVER_PG_DSN in bal-pusher, Dockerfiles, scripts and docs instead of the BAL_PUSHER_DB_* duplicates - Default BAL_SERVER_URL to http://127.0.0.1:9133 - Extract PostgreSQL container startup into a shared pg-server.sh sourced by bal-server.sh and bal-pusher.sh - Read the Postgres password from BAL_PG_PASSWORD instead of hardcoding it, and stop printing the password-bearing DSN - Redact a real-looking Gitea token from .env.example (revoke it if it was live)
This commit is contained in:
11
.env.example
11
.env.example
@@ -3,8 +3,7 @@
|
|||||||
# DO NOT commit the real token to git!
|
# DO NOT commit the real token to git!
|
||||||
# This file is in .gitignore and should not be committed to git
|
# This file is in .gitignore and should not be committed to git
|
||||||
GITEA_API_TOKEN=your_gitea_api_token_here
|
GITEA_API_TOKEN=your_gitea_api_token_here
|
||||||
# Example: GITEA_API_TOKEN=***REMOVED***
|
# If a token was ever committed, revoke it and set a new one via the environment.
|
||||||
# (replace with your actual token after revoking the old one)
|
|
||||||
|
|
||||||
# === bal-server ===
|
# === bal-server ===
|
||||||
# !!! WARNING: Never bind to 0.0.0.0 in production. Use 127.0.0.1 and place
|
# !!! WARNING: Never bind to 0.0.0.0 in production. Use 127.0.0.1 and place
|
||||||
@@ -33,8 +32,14 @@ BAL_SERVER_ACTIX_DEFAULT_BURST=100
|
|||||||
BAL_SERVER_ACTIX_WORKERS=4
|
BAL_SERVER_ACTIX_WORKERS=4
|
||||||
BAL_SERVER_ACTIX_MAX_CONNECTIONS=100
|
BAL_SERVER_ACTIX_MAX_CONNECTIONS=100
|
||||||
|
|
||||||
|
# === PostgreSQL (optional; used by pg-server.sh) ===
|
||||||
|
# pg-server.sh requires BAL_PG_PASSWORD to be set; never commit a real password.
|
||||||
|
BAL_PG_PASSWORD=change_me
|
||||||
|
BAL_PG_USER=bal
|
||||||
|
BAL_PG_DB=baldb
|
||||||
|
|
||||||
# === bal-pusher ===
|
# === bal-pusher ===
|
||||||
BAL_PUSHER_DB_FILE=/var/bal/bal.db
|
BAL_SERVER_DB_FILE=/var/bal/bal.db
|
||||||
BAL_PUSHER_BITCOIN_DIR=/home/bal/.bitcoin
|
BAL_PUSHER_BITCOIN_DIR=/home/bal/.bitcoin
|
||||||
BAL_PUSHER_SEND_STATS=false
|
BAL_PUSHER_SEND_STATS=false
|
||||||
BAL_SERVER_URL=http://127.0.0.1:9137
|
BAL_SERVER_URL=http://127.0.0.1:9137
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ ENV RUST_LOG=info \
|
|||||||
BAL_SERVER_BIND_ADDRESS=127.0.0.1 \
|
BAL_SERVER_BIND_ADDRESS=127.0.0.1 \
|
||||||
BAL_SERVER_BIND_PORT=9137 \
|
BAL_SERVER_BIND_PORT=9137 \
|
||||||
BAL_SERVER_DB_FILE=/var/bal/bal.db \
|
BAL_SERVER_DB_FILE=/var/bal/bal.db \
|
||||||
BAL_PUSHER_DB_FILE=/var/bal/bal.db \
|
|
||||||
BAL_SERVER_URL=http://127.0.0.1:9137 \
|
BAL_SERVER_URL=http://127.0.0.1:9137 \
|
||||||
BAL_SERVER_PUB_KEY_PATH=/var/bal/public_key.pem \
|
BAL_SERVER_PUB_KEY_PATH=/var/bal/public_key.pem \
|
||||||
SSL_KEY_PATH=/var/bal/private_key.pem
|
SSL_KEY_PATH=/var/bal/private_key.pem
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ ENV RUST_LOG=info \
|
|||||||
BAL_SERVER_BIND_ADDRESS=127.0.0.1 \
|
BAL_SERVER_BIND_ADDRESS=127.0.0.1 \
|
||||||
BAL_SERVER_BIND_PORT=9137 \
|
BAL_SERVER_BIND_PORT=9137 \
|
||||||
BAL_SERVER_DB_FILE=/var/bal/bal.db \
|
BAL_SERVER_DB_FILE=/var/bal/bal.db \
|
||||||
BAL_PUSHER_DB_FILE=/var/bal/bal.db \
|
|
||||||
BAL_SERVER_URL=http://127.0.0.1:9137 \
|
BAL_SERVER_URL=http://127.0.0.1:9137 \
|
||||||
BAL_SERVER_PUB_KEY_PATH=/var/bal/public_key.pem \
|
BAL_SERVER_PUB_KEY_PATH=/var/bal/public_key.pem \
|
||||||
SSL_KEY_PATH=/var/bal/private_key.pem
|
SSL_KEY_PATH=/var/bal/private_key.pem
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ If no network is specified, defaults to `bitcoin`.
|
|||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `BAL_PUSHER_DB_FILE` | Path to the SQLite3 database file. | `bal.db` |
|
| `BAL_SERVER_DB_FILE` | Path to the SQLite3 database file. | `bal.db` |
|
||||||
| `BAL_PUSHER_SEND_STATS` | Send stats to welist server. | `false` |
|
| `BAL_PUSHER_SEND_STATS` | Send stats to welist server. | `false` |
|
||||||
| `BAL_SERVER_URL` | URL of bal-server (for stats reporting). | - |
|
| `BAL_SERVER_URL` | URL of bal-server (for stats reporting). | - |
|
||||||
| `SSL_KEY_PATH` | Ed25519 private key for signing stats reports. | `private_key.pem` |
|
| `SSL_KEY_PATH` | Ed25519 private key for signing stats reports. | `private_key.pem` |
|
||||||
|
|||||||
18
bal-pusher.sh
Normal file → Executable file
18
bal-pusher.sh
Normal file → Executable file
@@ -1,6 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
. "$SCRIPT_DIR/lib.sh"
|
||||||
|
|
||||||
|
WORKING_DIR=$(pwd)
|
||||||
|
|
||||||
export RUST_LOG=trace
|
export RUST_LOG=trace
|
||||||
|
|
||||||
export BAL_PUSHER_DB_FILE="$(pwd)/bal.db"
|
export BAL_SERVER_DB_FILE="$WORKING_DIR/bal.db"
|
||||||
|
export BAL_SERVER_DB_BACKEND="postgresql"
|
||||||
#export BAL_PUSHER_BITCOIN_COOKIE_FILE=/~/.bitcoin/.cookie
|
#export BAL_PUSHER_BITCOIN_COOKIE_FILE=/~/.bitcoin/.cookie
|
||||||
#export BAL_PUSHER_REGTEST_COOKIE_FILE=/~/.bitcoin/regtest/.cookie
|
#export BAL_PUSHER_REGTEST_COOKIE_FILE=/~/.bitcoin/regtest/.cookie
|
||||||
#export BAL_PUSHER_TESTNET_COOKIE_FILE=/~/.bitcoin/testnet3/.cookie
|
#export BAL_PUSHER_TESTNET_COOKIE_FILE=/~/.bitcoin/testnet3/.cookie
|
||||||
@@ -11,5 +20,10 @@ export BAL_PUSHER_SEND_STATS=true
|
|||||||
export WELIST_SERVER_URL=http://localhost:8086
|
export WELIST_SERVER_URL=http://localhost:8086
|
||||||
export WELIST_SKIP_URL_VALIDATION=true
|
export WELIST_SKIP_URL_VALIDATION=true
|
||||||
export BAL_SERVER_URL="http://127.0.0.1:9133"
|
export BAL_SERVER_URL="http://127.0.0.1:9133"
|
||||||
export SSL_KEY_PATH="$(pwd)/private_key.pem"
|
export SSL_KEY_PATH="$WORKING_DIR/private_key.pem"
|
||||||
|
|
||||||
|
if [ "$BAL_SERVER_DB_BACKEND" = "postgresql" ]; then
|
||||||
|
. "$SCRIPT_DIR/pg-server.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
cargo run --bin=bal-pusher regtest --features=pusher
|
cargo run --bin=bal-pusher regtest --features=pusher
|
||||||
|
|||||||
@@ -31,31 +31,7 @@ export BAL_SERVER_REGTEST_FIXED_FEE=1000
|
|||||||
export BAL_SERVER_DB_BACKEND="postgresql"
|
export BAL_SERVER_DB_BACKEND="postgresql"
|
||||||
|
|
||||||
if [ "$BAL_SERVER_DB_BACKEND" = "postgresql" ]; then
|
if [ "$BAL_SERVER_DB_BACKEND" = "postgresql" ]; then
|
||||||
PG_CONTAINER="bal-pg"
|
. "$SCRIPT_DIR/pg-server.sh"
|
||||||
PG_DSN="${BAL_SERVER_PG_DSN:-postgres://bal:***REMOVED***@localhost:5432/baldb}"
|
|
||||||
|
|
||||||
docker rm -f "$PG_CONTAINER" 2>/dev/null || true
|
|
||||||
echo_i "Starting PostgreSQL container..."
|
|
||||||
docker run -d --name "$PG_CONTAINER" \
|
|
||||||
-e POSTGRES_USER=bal \
|
|
||||||
-e POSTGRES_PASSWORD=***REMOVED*** \
|
|
||||||
-e POSTGRES_DB=baldb \
|
|
||||||
-p 5432:5432 postgres:16-alpine
|
|
||||||
|
|
||||||
echo_i "Waiting for PostgreSQL..."
|
|
||||||
until docker exec "$PG_CONTAINER" pg_isready -U bal >/dev/null 2>&1; do
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
echo_i "PostgreSQL ready at $PG_DSN"
|
|
||||||
export BAL_SERVER_PG_DSN="$PG_DSN"
|
|
||||||
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
echo_i "Stopping PostgreSQL container..."
|
|
||||||
docker stop "$PG_CONTAINER" >/dev/null 2>&1
|
|
||||||
docker rm "$PG_CONTAINER" >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
trap cleanup EXIT
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cargo run --bin=bal-server
|
cargo run --bin=bal-server
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ BAL_SERVER_INFO="$info"
|
|||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
bal_pusher_conf=$(cat << EOF
|
bal_pusher_conf=$(cat << EOF
|
||||||
BAL_PUSHER_DB_FILE=/home/bal/bal.db
|
BAL_SERVER_DB_FILE=/home/bal/bal.db
|
||||||
BAL_PUSHER_BITCOIN_COOKIE_FILE=/home/bitcoin/.bitcoin/.cookie
|
BAL_PUSHER_BITCOIN_COOKIE_FILE=/home/bitcoin/.bitcoin/.cookie
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ This is the async daemon that monitors the blockchain and pushes pending transac
|
|||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
All configuration is via environment variables (no config files):
|
All configuration is via environment variables (no config files):
|
||||||
- `BAL_PUSHER_DB_FILE`: Path to SQLite database.
|
- `BAL_SERVER_DB_FILE`: Path to SQLite database.
|
||||||
- `BAL_PUSHER_BITCOIN_DIR`: Bitcoin data directory (for cookie file path).
|
- `BAL_PUSHER_BITCOIN_DIR`: Bitcoin data directory (for cookie file path).
|
||||||
- `BAL_PUSHER_SEND_STATS`: Enable/disable remote stats reporting.
|
- `BAL_PUSHER_SEND_STATS`: Enable/disable remote stats reporting.
|
||||||
- `BAL_SERVER_URL`: URL of the bal-server for internal communication.
|
- `BAL_SERVER_URL`: URL of the bal-server for internal communication.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
## Database Technology
|
## Database Technology
|
||||||
- **Engine:** `sqlite` (Rust `sqlite` crate, version 0.34.0)
|
- **Engine:** `sqlite` (Rust `sqlite` crate, version 0.34.0)
|
||||||
- **File:** `bal.db` (default, configurable via `BAL_SERVER_DB_FILE` / `BAL_PUSHER_DB_FILE`)
|
- **File:** `bal.db` (default, configurable via `BAL_SERVER_DB_FILE`)
|
||||||
- **Connection Management:** Shared `Arc<Mutex<Connection>>` in `bal-server`, single connection in `bal-pusher`.
|
- **Connection Management:** Shared `Arc<Mutex<Connection>>` in `bal-server`, single connection in `bal-pusher`.
|
||||||
- **WAL Mode:** Enabled via `PRAGMA journal_mode=WAL` with retry logic (up to 5 attempts) for concurrent access safety.
|
- **WAL Mode:** Enabled via `PRAGMA journal_mode=WAL` with retry logic (up to 5 attempts) for concurrent access safety.
|
||||||
- **Busy Timeout:** Set to 5000ms via `PRAGMA busy_timeout=5000`.
|
- **Busy Timeout:** Set to 5000ms via `PRAGMA busy_timeout=5000`.
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ Example: `BAL_SERVER_REGTEST_ADDRESS=tpub...`, `BAL_SERVER_BITCOIN_FIXED_FEE=500
|
|||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|----------|---------|-------------|
|
|----------|---------|-------------|
|
||||||
| `BAL_PUSHER_DB_FILE` | `"bal.db"` | Path to the SQLite database file |
|
| `BAL_SERVER_DB_FILE` | `"bal.db"` | Path to the SQLite database file |
|
||||||
| `BAL_PUSHER_BITCOIN_DIR` | `""` | Bitcoin data directory (for cookie file path resolution) |
|
| `BAL_PUSHER_BITCOIN_DIR` | `""` | Bitcoin data directory (for cookie file path resolution) |
|
||||||
| `BAL_PUSHER_SEND_STATS` | `false` | Enable/disable remote stats reporting |
|
| `BAL_PUSHER_SEND_STATS` | `false` | Enable/disable remote stats reporting |
|
||||||
| `BAL_SERVER_URL` | `"http://localhost/"` | URL of the bal-server for internal communication |
|
| `BAL_SERVER_URL` | `"http://127.0.0.1:9133"` | URL of the bal-server for internal communication |
|
||||||
| `SSL_KEY_PATH` | `"privkey.pem"` | Path to Ed25519 private key for signing stats |
|
| `SSL_KEY_PATH` | `"privkey.pem"` | Path to Ed25519 private key for signing stats |
|
||||||
| `BAL_PUSHER_PREFER_IPV6` | `false` | Pin HTTP connection to first IPv6 address (for broken IPv4 routes) |
|
| `BAL_PUSHER_PREFER_IPV6` | `false` | Pin HTTP connection to first IPv6 address (for broken IPv4 routes) |
|
||||||
| `WELIST_SERVER_URL` | `"https://welist.bitcoin-after.life"` | URL to POST signed stats to (validated against SSRF) |
|
| `WELIST_SERVER_URL` | `"https://welist.bitcoin-after.life"` | URL to POST signed stats to (validated against SSRF) |
|
||||||
|
|||||||
34
pg-server.sh
Executable file
34
pg-server.sh
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
. "$SCRIPT_DIR/lib.sh"
|
||||||
|
|
||||||
|
PG_CONTAINER="bal-pg"
|
||||||
|
PG_USER="${BAL_PG_USER:-bal}"
|
||||||
|
PG_DB="${BAL_PG_DB:-baldb}"
|
||||||
|
# The password MUST come from the environment; never hardcode it.
|
||||||
|
PG_PASSWORD="${BAL_PG_PASSWORD:?BAL_PG_PASSWORD must be set (see .env.example)}"
|
||||||
|
PG_DSN="${BAL_SERVER_PG_DSN:-postgres://${PG_USER}:${PG_PASSWORD}@localhost:5432/${PG_DB}}"
|
||||||
|
|
||||||
|
if docker ps --format '{{.Names}}' | grep -q "^${PG_CONTAINER}$"; then
|
||||||
|
echo_i "PostgreSQL container '$PG_CONTAINER' is already running"
|
||||||
|
elif docker ps -a --format '{{.Names}}' | grep -q "^${PG_CONTAINER}$"; then
|
||||||
|
echo_i "Starting existing PostgreSQL container '$PG_CONTAINER'..."
|
||||||
|
docker start "$PG_CONTAINER" >/dev/null 2>&1
|
||||||
|
else
|
||||||
|
echo_i "Creating PostgreSQL container '$PG_CONTAINER'..."
|
||||||
|
docker run -d --name "$PG_CONTAINER" \
|
||||||
|
-e POSTGRES_USER="$PG_USER" \
|
||||||
|
-e POSTGRES_PASSWORD="$PG_PASSWORD" \
|
||||||
|
-e POSTGRES_DB="$PG_DB" \
|
||||||
|
-p 5432:5432 postgres:16-alpine
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo_i "Waiting for PostgreSQL..."
|
||||||
|
until docker exec "$PG_CONTAINER" pg_isready -U "$PG_USER" >/dev/null 2>&1; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
# Do not echo the DSN: it embeds the password.
|
||||||
|
echo_s "PostgreSQL ready (user=$PG_USER, db=$PG_DB, host=localhost:5432)"
|
||||||
|
export BAL_SERVER_PG_DSN="$PG_DSN"
|
||||||
@@ -46,9 +46,9 @@ struct MyConfig {
|
|||||||
impl Default for MyConfig {
|
impl Default for MyConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
MyConfig {
|
MyConfig {
|
||||||
db_backend: env::var("BAL_PUSHER_DB_BACKEND").unwrap_or("sqlite".to_string()),
|
db_backend: env::var("BAL_SERVER_DB_BACKEND").unwrap_or("sqlite".to_string()),
|
||||||
db_file: env::var("BAL_PUSHER_DB_FILE").unwrap_or("bal.db".to_string()),
|
db_file: env::var("BAL_SERVER_DB_FILE").unwrap_or("bal.db".to_string()),
|
||||||
pg_dsn: env::var("BAL_PUSHER_PG_DSN").unwrap_or_default(),
|
pg_dsn: env::var("BAL_SERVER_PG_DSN").unwrap_or_default(),
|
||||||
bitcoin_dir: env::var("BAL_PUSHER_BITCOIN_DIR").unwrap_or("".to_string()),
|
bitcoin_dir: env::var("BAL_PUSHER_BITCOIN_DIR").unwrap_or("".to_string()),
|
||||||
regtest: get_network_params_default(Network::Regtest),
|
regtest: get_network_params_default(Network::Regtest),
|
||||||
testnet: get_network_params_default(Network::Testnet),
|
testnet: get_network_params_default(Network::Testnet),
|
||||||
@@ -59,7 +59,7 @@ impl Default for MyConfig {
|
|||||||
.unwrap_or("false".to_string())
|
.unwrap_or("false".to_string())
|
||||||
.parse::<bool>()
|
.parse::<bool>()
|
||||||
.unwrap_or(false),
|
.unwrap_or(false),
|
||||||
url: env::var("BAL_SERVER_URL").unwrap_or("http://localhost/".to_string()),
|
url: env::var("BAL_SERVER_URL").unwrap_or("http://127.0.0.1:9133".to_string()),
|
||||||
ssl_key_path: env::var("SSL_KEY_PATH").unwrap_or("privkey.pem".to_string()),
|
ssl_key_path: env::var("SSL_KEY_PATH").unwrap_or("privkey.pem".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -423,13 +423,13 @@ fn sign_message(private_key_path: &str, message: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_env(cfg: &mut MyConfig) {
|
fn parse_env(cfg: &mut MyConfig) {
|
||||||
if let Ok(value) = env::var("BAL_PUSHER_DB_BACKEND") {
|
if let Ok(value) = env::var("BAL_SERVER_DB_BACKEND") {
|
||||||
cfg.db_backend = value;
|
cfg.db_backend = value;
|
||||||
}
|
}
|
||||||
if let Ok(value) = env::var("BAL_PUSHER_DB_FILE") {
|
if let Ok(value) = env::var("BAL_SERVER_DB_FILE") {
|
||||||
cfg.db_file = value;
|
cfg.db_file = value;
|
||||||
}
|
}
|
||||||
if let Ok(value) = env::var("BAL_PUSHER_PG_DSN") {
|
if let Ok(value) = env::var("BAL_SERVER_PG_DSN") {
|
||||||
cfg.pg_dsn = value;
|
cfg.pg_dsn = value;
|
||||||
}
|
}
|
||||||
cfg.regtest = parse_env_netconfig(cfg, "regtest");
|
cfg.regtest = parse_env_netconfig(cfg, "regtest");
|
||||||
|
|||||||
Reference in New Issue
Block a user