exchange: manual start/health + zz-hacktivism conf drop-in
This commit is contained in:
parent
07e7131850
commit
5920296ae4
10 changed files with 1027 additions and 0 deletions
3
configs/taler-exchange/taler-exchange.conf.includes.txt
Normal file
3
configs/taler-exchange/taler-exchange.conf.includes.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
32:@inline-matching@ conf.d/*.conf
|
||||||
|
35:@inline@ overrides.conf
|
||||||
|
50:@inline@ exchange-overrides.conf
|
||||||
2
configs/taler-exchange/zz-hacktivism.conf
Normal file
2
configs/taler-exchange/zz-hacktivism.conf
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[exchange]
|
||||||
|
CURRENCY = GOA
|
||||||
35
scripts/taler-exchange/archive/README.md
Normal file
35
scripts/taler-exchange/archive/README.md
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Exchange archive / bootstrap
|
||||||
|
|
||||||
|
## `exchange-bootstrap.sh` (greenfield only)
|
||||||
|
|
||||||
|
One-shot bootstrap for a **new** exchange container. **Not** used for daily ops.
|
||||||
|
|
||||||
|
Includes current **GOA exploration currency**:
|
||||||
|
|
||||||
|
- `exchange-overrides.conf` pattern (no `zz-*`)
|
||||||
|
- `PORT = 9011`, `SERVE = tcp`
|
||||||
|
- Unit names: Yotta…Atomic-GOA (scale −8…24)
|
||||||
|
- ATM `common_amounts` 10…1000
|
||||||
|
- Full 1–2–5 **coin** ladder (Micro-GOA … 10 GOA) in `conf.d/exchange-coins.conf`
|
||||||
|
|
||||||
|
After bootstrap:
|
||||||
|
|
||||||
|
1. `/root/start_base_services_for_taler_exchange.sh` (root)
|
||||||
|
2. `./start_exchange.sh` as `taler-exchange-httpd`
|
||||||
|
3. Offline: wire enable + denom/signkey sign for `/keys`
|
||||||
|
Live helpers: `../wire-enable-and-upload.sh`, `../offline-sign-upload-keys.sh`, `../start_wire_helpers.sh`
|
||||||
|
|
||||||
|
## Removed
|
||||||
|
|
||||||
|
| Script | Why |
|
||||||
|
|--------|-----|
|
||||||
|
| `exchange-start-all.sh` | Redundant with base + `start_exchange.sh` |
|
||||||
|
| old zz-hacktivism bootstrap | Wrong ports/currency; superseded |
|
||||||
|
|
||||||
|
## Daily layout (merchant model)
|
||||||
|
|
||||||
|
| Path | User |
|
||||||
|
|------|------|
|
||||||
|
| `/root/start_base_services_for_taler_exchange.sh` | root |
|
||||||
|
| `/usr/local/bin/start_exchange.sh` | `taler-exchange-httpd` |
|
||||||
|
| `/usr/local/bin/check_exchange-health.sh` | httpd / any |
|
||||||
451
scripts/taler-exchange/archive/exchange-bootstrap.sh
Executable file
451
scripts/taler-exchange/archive/exchange-bootstrap.sh
Executable file
|
|
@ -0,0 +1,451 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Greenfield bootstrap for exchange.hacktivism.ch (GOA exploration currency).
|
||||||
|
# Run as root inside container. Not for daily ops — use start_base + start_exchange.
|
||||||
|
#
|
||||||
|
# Writes:
|
||||||
|
# /etc/taler-exchange/exchange-overrides.conf
|
||||||
|
# /etc/taler-exchange/conf.d/exchange-coins.conf
|
||||||
|
# Ensures main conf inlines exchange-overrides.conf (merchant pattern).
|
||||||
|
# Does NOT use conf.d/zz-*.
|
||||||
|
#
|
||||||
|
# After this: offline denom sign + wire still required for /keys withdraw.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
CONF=/etc/taler-exchange/taler-exchange.conf
|
||||||
|
OV=/etc/taler-exchange/exchange-overrides.conf
|
||||||
|
COINS=/etc/taler-exchange/conf.d/exchange-coins.conf
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
echo "Run as root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== 1. postgres ==="
|
||||||
|
/etc/init.d/postgresql start
|
||||||
|
sleep 2
|
||||||
|
pg_isready || true
|
||||||
|
|
||||||
|
echo "=== 2. master key (offline user) ==="
|
||||||
|
mkdir -p /var/lib/taler-exchange/offline
|
||||||
|
chown -R taler-exchange-offline:taler-exchange-offline /var/lib/taler-exchange/offline
|
||||||
|
chown taler-exchange-offline:taler-exchange-offline /var/lib/taler-exchange 2>/dev/null || true
|
||||||
|
OUT=$(runuser -u taler-exchange-offline -- taler-exchange-offline -c "$CONF" setup 2>&1) || true
|
||||||
|
echo "$OUT"
|
||||||
|
MASTER_PUB=$(echo "$OUT" | grep -oE '[A-Z0-9]{40,}' | tail -1)
|
||||||
|
if [ -z "${MASTER_PUB:-}" ]; then
|
||||||
|
echo "ERROR: no master public key from offline setup" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "MASTER_PUBLIC_KEY=$MASTER_PUB"
|
||||||
|
ATTR_KEY=$(openssl rand -hex 32)
|
||||||
|
SECRETS_DIR=/etc/taler-exchange/secrets
|
||||||
|
mkdir -p "$SECRETS_DIR"
|
||||||
|
cat >"$SECRETS_DIR/exchange-attribute-encryption.secret.conf" <<SEOF
|
||||||
|
# generated by exchange-bootstrap.sh
|
||||||
|
[exchange]
|
||||||
|
ATTRIBUTE_ENCRYPTION_KEY = ${ATTR_KEY}
|
||||||
|
SEOF
|
||||||
|
chmod 640 "$SECRETS_DIR/exchange-attribute-encryption.secret.conf"
|
||||||
|
chown root:taler-exchange-httpd "$SECRETS_DIR/exchange-attribute-encryption.secret.conf" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "=== 3. exchange-overrides.conf (site; not zz-*) ==="
|
||||||
|
# Ensure main conf inlines overrides (merchant pattern)
|
||||||
|
if ! grep -q 'exchange-overrides.conf' "$CONF" 2>/dev/null; then
|
||||||
|
printf '\n# Manual site overrides (merchant pattern)\n@inline@ exchange-overrides.conf\n' >>"$CONF"
|
||||||
|
fi
|
||||||
|
# Remove legacy zz drop-ins if present
|
||||||
|
rm -f /etc/taler-exchange/conf.d/zz-hacktivism.conf \
|
||||||
|
/etc/taler-exchange/conf.d/zz-hacktivism-coins.conf 2>/dev/null || true
|
||||||
|
|
||||||
|
cat >"$OV" <<EOF
|
||||||
|
# Manual site overrides for exchange.hacktivism.ch (GOA exploration currency).
|
||||||
|
# Same role as /etc/taler-merchant/merchant-overrides.conf on taler-hacktivism.
|
||||||
|
# Do not edit overrides.conf (tooling). Do not edit package conf.d defaults.
|
||||||
|
# No conf.d/zz-* drop-ins.
|
||||||
|
|
||||||
|
[exchange]
|
||||||
|
CURRENCY = GOA
|
||||||
|
CURRENCY_ROUND_UNIT = GOA:0.00000001
|
||||||
|
TINY_AMOUNT = GOA:0.00000001
|
||||||
|
DEFAULT_P2P_EXPIRATION = 14 days
|
||||||
|
BASE_URL = https://exchange.hacktivism.ch/
|
||||||
|
SERVE = tcp
|
||||||
|
PORT = 9011
|
||||||
|
MASTER_PUBLIC_KEY = ${MASTER_PUB}
|
||||||
|
# ATTRIBUTE_ENCRYPTION_KEY via @inline-secret@ (see secrets/)
|
||||||
|
@inline-secret@ exchange-attribute-encryption ../secrets/exchange-attribute-encryption.secret.conf
|
||||||
|
|
||||||
|
[currency-goa]
|
||||||
|
ENABLED = YES
|
||||||
|
name = "GOA exploration currency"
|
||||||
|
code = GOA
|
||||||
|
# SI display units. taler-exchange rejects scale keys outside [-8, 24] (no Ronna/Quetta).
|
||||||
|
fractional_input_digits = 8
|
||||||
|
fractional_normal_digits = 0
|
||||||
|
fractional_trailing_zero_digits = 0
|
||||||
|
alt_unit_names_are_symbols = NO
|
||||||
|
alt_unit_names = {"24":"Yotta-GOA","21":"Zetta-GOA","18":"Exa-GOA","15":"Peta-GOA","12":"Tera-GOA","9":"Giga-GOA","6":"Mega-GOA","3":"Kilo-GOA","0":"GOA","-1":"Deci-GOA","-2":"Centi-GOA","-3":"Milli-GOA","-6":"Micro-GOA","-7":"Deci-Micro-GOA","-8":"Atomic-GOA"}
|
||||||
|
common_amounts = "GOA:10 GOA:20 GOA:50 GOA:100 GOA:200 GOA:1000"
|
||||||
|
|
||||||
|
### Disable package demonstrator currencies (like merchant-overrides)
|
||||||
|
[currency-kudos]
|
||||||
|
ENABLED = NO
|
||||||
|
|
||||||
|
[currency-testkudos]
|
||||||
|
ENABLED = NO
|
||||||
|
EOF
|
||||||
|
echo "Wrote $OV"
|
||||||
|
grep -E '^(name|code|PORT|CURRENCY|alt_unit|fractional_input|common_)' "$OV" || true
|
||||||
|
|
||||||
|
echo "=== 4. GOA coin denominations (1–2–5 ladder) ==="
|
||||||
|
if [ -f "$COINS" ] && ! grep -q 'VALUE = GOA' "$COINS" 2>/dev/null; then
|
||||||
|
mv "$COINS" "${COINS}.package-kudos"
|
||||||
|
echo "Moved package coins -> ${COINS}.package-kudos"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >"$COINS" << 'COINS_EOF'
|
||||||
|
# GOA denominations for exchange.hacktivism.ch
|
||||||
|
# Units: 1 GOA = 1000 mGOA = 1_000_000 uGOA
|
||||||
|
# VALUE uses base currency; coin sections cover 1–2–5 ladders at u/m/whole scale.
|
||||||
|
|
||||||
|
# --- uGOA (10^-6 GOA) ---
|
||||||
|
[coin_goa_0_000001]
|
||||||
|
VALUE = GOA:0.000001
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_000002]
|
||||||
|
VALUE = GOA:0.000002
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_000005]
|
||||||
|
VALUE = GOA:0.000005
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_00001]
|
||||||
|
VALUE = GOA:0.00001
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_00002]
|
||||||
|
VALUE = GOA:0.00002
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_00005]
|
||||||
|
VALUE = GOA:0.00005
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_0001]
|
||||||
|
VALUE = GOA:0.0001
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_0002]
|
||||||
|
VALUE = GOA:0.0002
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_0005]
|
||||||
|
VALUE = GOA:0.0005
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
# --- mGOA (10^-3 GOA) ---
|
||||||
|
[coin_goa_0_001]
|
||||||
|
VALUE = GOA:0.001
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_002]
|
||||||
|
VALUE = GOA:0.002
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_005]
|
||||||
|
VALUE = GOA:0.005
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_01]
|
||||||
|
VALUE = GOA:0.01
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_02]
|
||||||
|
VALUE = GOA:0.02
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_05]
|
||||||
|
VALUE = GOA:0.05
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_1]
|
||||||
|
VALUE = GOA:0.1
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_2]
|
||||||
|
VALUE = GOA:0.2
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_0_5]
|
||||||
|
VALUE = GOA:0.5
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
# --- whole GOA ---
|
||||||
|
[coin_goa_1_0]
|
||||||
|
VALUE = GOA:1
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_2_0]
|
||||||
|
VALUE = GOA:2
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_5_0]
|
||||||
|
VALUE = GOA:5
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_10_0]
|
||||||
|
VALUE = GOA:10
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_20_0]
|
||||||
|
VALUE = GOA:20
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_50_0]
|
||||||
|
VALUE = GOA:50
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_100_0]
|
||||||
|
VALUE = GOA:100
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_200_0]
|
||||||
|
VALUE = GOA:200
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
|
||||||
|
[coin_goa_1000_0]
|
||||||
|
VALUE = GOA:1000
|
||||||
|
DURATION_WITHDRAW = 7 days
|
||||||
|
DURATION_SPEND = 2 years
|
||||||
|
DURATION_LEGAL = 3 years
|
||||||
|
FEE_WITHDRAW = GOA:0
|
||||||
|
FEE_DEPOSIT = GOA:0
|
||||||
|
FEE_REFRESH = GOA:0
|
||||||
|
FEE_REFUND = GOA:0
|
||||||
|
RSA_KEYSIZE = 2048
|
||||||
|
CIPHER = RSA
|
||||||
|
COINS_EOF
|
||||||
|
|
||||||
|
echo "Wrote $COINS ($(grep -c '^\[coin_' "$COINS") coin sections)"
|
||||||
|
|
||||||
|
echo "=== 5. database ==="
|
||||||
|
taler-exchange-dbconfig 2>&1 || true
|
||||||
|
runuser -u taler-exchange-httpd -- taler-exchange-dbinit -c "$CONF" 2>&1 || true
|
||||||
|
|
||||||
|
echo "=== 6. next steps (manual) ==="
|
||||||
|
echo " - /root/start_base_services_for_taler_exchange.sh # root: secmods + shell as httpd"
|
||||||
|
echo " - ./start_exchange.sh # as taler-exchange-httpd"
|
||||||
|
echo " - offline: sign denominations + wire accounts for /keys"
|
||||||
|
echo " - MASTER_PUBLIC_KEY=$MASTER_PUB"
|
||||||
|
echo "DONE bootstrap"
|
||||||
88
scripts/taler-exchange/check_exchange-health.sh
Executable file
88
scripts/taler-exchange/check_exchange-health.sh
Executable file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Health check for manual taler-exchange (same style as check_merchant-health.sh).
|
||||||
|
# Runnable as taler-exchange-httpd (or any user that can see processes + curl localhost).
|
||||||
|
|
||||||
|
CONF=/etc/taler-exchange/taler-exchange.conf
|
||||||
|
SOCK=/run/taler-exchange/httpd/exchange-http.sock
|
||||||
|
|
||||||
|
green() { echo -e "\e[32m$1\e[0m"; }
|
||||||
|
red() { echo -e "\e[31m$1\e[0m"; }
|
||||||
|
yellow() { echo -e "\e[33m$1\e[0m"; }
|
||||||
|
|
||||||
|
fail=0
|
||||||
|
ok() { green "[OK] $1"; }
|
||||||
|
bad() { red "[FAIL] $1"; fail=1; }
|
||||||
|
warn() { yellow "[WARN] $1"; }
|
||||||
|
|
||||||
|
echo "=== Taler Exchange Health Check ==="
|
||||||
|
|
||||||
|
# 1. secmods (started by root base script)
|
||||||
|
for p in taler-exchange-secmod-rsa taler-exchange-secmod-cs taler-exchange-secmod-eddsa; do
|
||||||
|
if pgrep -f "$p" >/dev/null 2>&1; then
|
||||||
|
ok "process $p"
|
||||||
|
else
|
||||||
|
bad "process $p not running"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 2. httpd
|
||||||
|
if pgrep -f taler-exchange-httpd >/dev/null 2>&1; then
|
||||||
|
ok "process taler-exchange-httpd"
|
||||||
|
else
|
||||||
|
bad "process taler-exchange-httpd is NOT running"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. serving mode
|
||||||
|
SERVE=$(taler-exchange-config -c "$CONF" -s exchange -o SERVE 2>/dev/null || echo unix)
|
||||||
|
PORT=$(taler-exchange-config -c "$CONF" -s exchange -o PORT 2>/dev/null || echo 9011)
|
||||||
|
|
||||||
|
if [ "$SERVE" = "tcp" ]; then
|
||||||
|
if curl -sf -m 3 "http://127.0.0.1:${PORT}/config" >/dev/null 2>&1; then
|
||||||
|
ok "HTTP /config on 127.0.0.1:${PORT}"
|
||||||
|
elif curl -sf -m 3 "http://127.0.0.1:${PORT}/keys" >/dev/null 2>&1; then
|
||||||
|
ok "HTTP /keys on 127.0.0.1:${PORT}"
|
||||||
|
else
|
||||||
|
bad "no HTTP response on 127.0.0.1:${PORT} (/config|/keys)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ -S "$SOCK" ]; then
|
||||||
|
ok "socket $SOCK"
|
||||||
|
else
|
||||||
|
bad "socket does NOT exist: $SOCK"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 4. wire helpers — ensure (no systemd) then require
|
||||||
|
if [ "${SKIP_ENSURE:-0}" != "1" ]; then
|
||||||
|
if [ -x /usr/local/bin/ensure_exchange_helpers.sh ]; then
|
||||||
|
echo "--- ensure_exchange_helpers ---"
|
||||||
|
/usr/local/bin/ensure_exchange_helpers.sh || warn "ensure_exchange_helpers exited non-zero"
|
||||||
|
elif [ -x "$(dirname "$0")/ensure_exchange_helpers.sh" ]; then
|
||||||
|
echo "--- ensure_exchange_helpers ---"
|
||||||
|
"$(dirname "$0")/ensure_exchange_helpers.sh" || warn "ensure_exchange_helpers exited non-zero"
|
||||||
|
elif [ -x /root/ensure_exchange_helpers.sh ]; then
|
||||||
|
echo "--- ensure_exchange_helpers ---"
|
||||||
|
/root/ensure_exchange_helpers.sh || warn "ensure_exchange_helpers exited non-zero"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
live_helper() {
|
||||||
|
local p="$1"
|
||||||
|
# COMM is 15 chars; use full cmdline match
|
||||||
|
pgrep -f "(^|/)(${p})( |$)" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
for p in taler-exchange-aggregator taler-exchange-wirewatch taler-exchange-transfer taler-exchange-closer; do
|
||||||
|
if live_helper "$p"; then
|
||||||
|
ok "process $p"
|
||||||
|
else
|
||||||
|
bad "process $p not running (settlement needs transfer+aggregator)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$fail" -eq 0 ]; then
|
||||||
|
green "=== ALL CRITICAL CHECKS PASSED ==="
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
red "=== SOME CHECKS FAILED ==="
|
||||||
|
exit 1
|
||||||
62
scripts/taler-exchange/offline-sign-upload-keys.sh
Executable file
62
scripts/taler-exchange/offline-sign-upload-keys.sh
Executable file
|
|
@ -0,0 +1,62 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Offline: download future keys from local exchange, sign, upload. Restore public BASE_URL.
|
||||||
|
# Run as root inside taler-exchange-hacktivism.
|
||||||
|
set -euo pipefail
|
||||||
|
CONF=/etc/taler-exchange/taler-exchange.conf
|
||||||
|
OV=/etc/taler-exchange/exchange-overrides.conf
|
||||||
|
PUBLIC='https://exchange.hacktivism.ch/'
|
||||||
|
LOCAL='http://127.0.0.1:9011/'
|
||||||
|
|
||||||
|
[ "$(id -u)" -eq 0 ] || { echo "root only"; exit 1; }
|
||||||
|
|
||||||
|
sed -i "s|^BASE_URL = .*|BASE_URL = ${LOCAL}|" "$OV"
|
||||||
|
echo "BASE_URL=$(grep '^BASE_URL' "$OV")"
|
||||||
|
|
||||||
|
echo "=== download ==="
|
||||||
|
if ! runuser -u taler-exchange-offline -- \
|
||||||
|
taler-exchange-offline -c "$CONF" -L INFO download > /tmp/future-keys.json 2>/tmp/dl.err; then
|
||||||
|
echo "download failed:"; cat /tmp/dl.err
|
||||||
|
# still show size
|
||||||
|
fi
|
||||||
|
echo "dl_err:"; cat /tmp/dl.err | tail -30
|
||||||
|
echo "dl_size=$(wc -c </tmp/future-keys.json 2>/dev/null || echo 0)"
|
||||||
|
head -c 400 /tmp/future-keys.json 2>/dev/null; echo
|
||||||
|
|
||||||
|
if [ ! -s /tmp/future-keys.json ]; then
|
||||||
|
echo "empty download — check secmod connectivity / management API"
|
||||||
|
sed -i "s|^BASE_URL = .*|BASE_URL = ${PUBLIC}|" "$OV"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== sign ==="
|
||||||
|
runuser -u taler-exchange-offline -- \
|
||||||
|
taler-exchange-offline -c "$CONF" -L INFO sign < /tmp/future-keys.json > /tmp/signed-keys.json 2>/tmp/sg.err
|
||||||
|
echo "sg_err:"; cat /tmp/sg.err | tail -20
|
||||||
|
echo "sg_size=$(wc -c </tmp/signed-keys.json)"
|
||||||
|
|
||||||
|
echo "=== upload ==="
|
||||||
|
runuser -u taler-exchange-offline -- \
|
||||||
|
taler-exchange-offline -c "$CONF" -L INFO upload < /tmp/signed-keys.json 2>/tmp/up.err
|
||||||
|
echo "up_err:"; cat /tmp/up.err | tail -20
|
||||||
|
|
||||||
|
sed -i "s|^BASE_URL = .*|BASE_URL = ${PUBLIC}|" "$OV"
|
||||||
|
echo "BASE_URL restored=$(grep '^BASE_URL' "$OV")"
|
||||||
|
|
||||||
|
echo "=== /keys probe ==="
|
||||||
|
sleep 1
|
||||||
|
# wake suspended handlers with a tiny delay
|
||||||
|
for i in 1 2 3 4 5 6; do
|
||||||
|
code=$(curl -sS -m 12 -o /tmp/keys.json -w '%{http_code}' http://127.0.0.1:9011/keys || true)
|
||||||
|
sz=$(wc -c </tmp/keys.json 2>/dev/null || echo 0)
|
||||||
|
echo "try $i code=$code size=$sz"
|
||||||
|
if [ "$code" = "200" ] && [ "$sz" -gt 200 ]; then
|
||||||
|
echo KEYS_OK
|
||||||
|
head -c 300 /tmp/keys.json; echo
|
||||||
|
grep -oE '"master_public_key"[[:space:]]*:[[:space:]]*"[^"]+"' /tmp/keys.json | head -1 || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo KEYS_FAIL
|
||||||
|
tail -25 /var/log/taler-exchange/taler-exchange-httpd-*.log 2>/dev/null | tail -25
|
||||||
|
exit 1
|
||||||
148
scripts/taler-exchange/start_base_services_for_taler_exchange.sh
Executable file
148
scripts/taler-exchange/start_base_services_for_taler_exchange.sh
Executable file
|
|
@ -0,0 +1,148 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Root: base services for manual exchange (like merchant start_base_services_for_taler.sh).
|
||||||
|
# Then interactive shell as taler-exchange-httpd → run start_exchange.sh there.
|
||||||
|
#
|
||||||
|
# Secmods run as dedicated users (not httpd) — started here as root.
|
||||||
|
# httpd is started by /usr/local/bin/start_exchange.sh as taler-exchange-httpd.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# /root/start_base_services_for_taler_exchange.sh
|
||||||
|
# /root/start_base_services_for_taler_exchange.sh --no-shell
|
||||||
|
|
||||||
|
set -e
|
||||||
|
CONF=/etc/taler-exchange/taler-exchange.conf
|
||||||
|
LOG_DIR=/var/log/taler-exchange
|
||||||
|
PWD_BIN=/usr/local/bin
|
||||||
|
EXCHANGE_STARTER=start_exchange.sh
|
||||||
|
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
echo "Run as root" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
NO_SHELL=0
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--no-shell|-n) NO_SHELL=1 ;;
|
||||||
|
--help|-h)
|
||||||
|
echo "Usage: $0 [--no-shell]"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- Debian postgresql defaults (pg_createcluster layout) ---
|
||||||
|
ensure_postgresql() {
|
||||||
|
echo " Debian perms on /etc/postgresql + data/log/run..."
|
||||||
|
if [ -d /etc/postgresql ]; then
|
||||||
|
chown -R root:postgres /etc/postgresql
|
||||||
|
find /etc/postgresql -type d -exec chmod 755 {} \;
|
||||||
|
find /etc/postgresql -type f -name '*.conf' -exec chmod 640 {} \;
|
||||||
|
fi
|
||||||
|
chown -R postgres:postgres /var/lib/postgresql /var/log/postgresql 2>/dev/null || true
|
||||||
|
mkdir -p /var/run/postgresql
|
||||||
|
chown postgres:postgres /var/run/postgresql
|
||||||
|
chmod 2775 /var/run/postgresql 2>/dev/null || chmod 775 /var/run/postgresql
|
||||||
|
|
||||||
|
if pg_isready -q 2>/dev/null; then
|
||||||
|
echo " already accepting connections"
|
||||||
|
pg_isready || true
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f /var/run/postgresql/.s.PGSQL.*.lock 2>/dev/null || true
|
||||||
|
if ! pgrep -u postgres -x postgres >/dev/null 2>&1; then
|
||||||
|
rm -f /var/lib/postgresql/*/main/postmaster.pid 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v pg_ctlcluster >/dev/null 2>&1 && command -v pg_lsclusters >/dev/null 2>&1; then
|
||||||
|
while read -r ver name _rest; do
|
||||||
|
[ -n "$ver" ] || continue
|
||||||
|
echo " pg_ctlcluster $ver $name start"
|
||||||
|
pg_ctlcluster "$ver" "$name" start 2>/dev/null || true
|
||||||
|
done < <(pg_lsclusters --no-header 2>/dev/null || true)
|
||||||
|
fi
|
||||||
|
if ! pg_isready -q 2>/dev/null; then
|
||||||
|
if [ -x /etc/init.d/postgresql ]; then
|
||||||
|
/etc/init.d/postgresql start || true
|
||||||
|
else
|
||||||
|
service postgresql start || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
pg_isready || true
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Create log + runtime dirs... giving permission to taler-exchange users:"
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
mkdir -p /run/taler-exchange/secmod-rsa /run/taler-exchange/secmod-cs \
|
||||||
|
/run/taler-exchange/secmod-eddsa /run/taler-exchange/httpd
|
||||||
|
chown root:root /run/taler-exchange
|
||||||
|
chmod 755 /run/taler-exchange
|
||||||
|
chown taler-exchange-secmod-rsa:taler-exchange-secmod /run/taler-exchange/secmod-rsa
|
||||||
|
chown taler-exchange-secmod-cs:taler-exchange-secmod /run/taler-exchange/secmod-cs
|
||||||
|
chown taler-exchange-secmod-eddsa:taler-exchange-secmod /run/taler-exchange/secmod-eddsa
|
||||||
|
chown taler-exchange-httpd:www-data /run/taler-exchange/httpd
|
||||||
|
chmod 755 /run/taler-exchange/secmod-rsa /run/taler-exchange/secmod-cs /run/taler-exchange/secmod-eddsa
|
||||||
|
chmod 750 /run/taler-exchange/httpd
|
||||||
|
chown taler-exchange-httpd: "$LOG_DIR"
|
||||||
|
chmod 755 "$LOG_DIR"
|
||||||
|
|
||||||
|
# Package default: each secmod user owns its tree (keys/ must not be root-owned).
|
||||||
|
mkdir -p /var/lib/taler-exchange/secmod-rsa /var/lib/taler-exchange/secmod-cs \
|
||||||
|
/var/lib/taler-exchange/secmod-eddsa
|
||||||
|
chown -R taler-exchange-secmod-rsa:taler-exchange-secmod /var/lib/taler-exchange/secmod-rsa
|
||||||
|
chown -R taler-exchange-secmod-cs:taler-exchange-secmod /var/lib/taler-exchange/secmod-cs
|
||||||
|
chown -R taler-exchange-secmod-eddsa:taler-exchange-secmod /var/lib/taler-exchange/secmod-eddsa
|
||||||
|
chmod 700 /var/lib/taler-exchange/secmod-rsa /var/lib/taler-exchange/secmod-cs \
|
||||||
|
/var/lib/taler-exchange/secmod-eddsa
|
||||||
|
|
||||||
|
echo "Start base services needed for Taler Exchange."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "1. postgresql:"
|
||||||
|
ensure_postgresql
|
||||||
|
|
||||||
|
# Linux COMM is 15 chars — never pgrep -x for long names; match full path in args.
|
||||||
|
start_bg() {
|
||||||
|
local user="$1"; shift
|
||||||
|
local name="$1"; shift
|
||||||
|
local bin="$1"
|
||||||
|
if ps -eo args= 2>/dev/null | grep -F "$bin" | grep -v grep >/dev/null 2>&1; then
|
||||||
|
echo " already running: $name"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo " start $name as $user"
|
||||||
|
nohup runuser -u "$user" -- "$@" >>"$LOG_DIR/${name}.log" 2>&1 </dev/null &
|
||||||
|
disown 2>/dev/null || true
|
||||||
|
sleep 0.3
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "2. crypto secmods:"
|
||||||
|
start_bg taler-exchange-secmod-rsa taler-exchange-secmod-rsa \
|
||||||
|
/usr/bin/taler-exchange-secmod-rsa -c "$CONF" -L INFO
|
||||||
|
start_bg taler-exchange-secmod-cs taler-exchange-secmod-cs \
|
||||||
|
/usr/bin/taler-exchange-secmod-cs -c "$CONF" -L INFO
|
||||||
|
start_bg taler-exchange-secmod-eddsa taler-exchange-secmod-eddsa \
|
||||||
|
/usr/bin/taler-exchange-secmod-eddsa -c "$CONF" -L INFO
|
||||||
|
|
||||||
|
echo "3. wire/db helpers (need wire config to stay up):"
|
||||||
|
start_bg taler-exchange-aggregator taler-exchange-aggregator \
|
||||||
|
/usr/bin/taler-exchange-aggregator -c "$CONF" -L INFO || true
|
||||||
|
start_bg taler-exchange-closer taler-exchange-closer \
|
||||||
|
/usr/bin/taler-exchange-closer -c "$CONF" -L INFO || true
|
||||||
|
start_bg taler-exchange-wire taler-exchange-wirewatch \
|
||||||
|
/usr/bin/taler-exchange-wirewatch -c "$CONF" -L INFO || true
|
||||||
|
start_bg taler-exchange-wire taler-exchange-transfer \
|
||||||
|
/usr/bin/taler-exchange-transfer -c "$CONF" -L INFO || true
|
||||||
|
|
||||||
|
if [ "$NO_SHELL" -eq 1 ]; then
|
||||||
|
echo "Base services started (--no-shell). Next: runuser -u taler-exchange-httpd -- $PWD_BIN/$EXCHANGE_STARTER [--restart]"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "4. Switching now to user taler-exchange-httpd, in $PWD_BIN; find executable $EXCHANGE_STARTER there!"
|
||||||
|
echo ""
|
||||||
|
cd "$PWD_BIN"
|
||||||
|
# same pattern as merchant: -u and -s/--shell are mutually exclusive on util-linux runuser
|
||||||
|
exec runuser -u taler-exchange-httpd -- bash
|
||||||
104
scripts/taler-exchange/start_exchange.sh
Executable file
104
scripts/taler-exchange/start_exchange.sh
Executable file
|
|
@ -0,0 +1,104 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Start / restart taler-exchange-httpd (manual, no systemd).
|
||||||
|
# Run as: taler-exchange-httpd
|
||||||
|
# Same role as start_merchant.sh for the merchant.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# start_exchange.sh
|
||||||
|
# start_exchange.sh --restart | -r
|
||||||
|
# start_exchange.sh --help
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: start_exchange.sh [--restart|-r] [--help|-h]
|
||||||
|
|
||||||
|
(default) Start taler-exchange-httpd if not already running.
|
||||||
|
--restart Stop live taler-exchange-httpd, then start cleanly.
|
||||||
|
Does not touch postgres/secmods/wire helpers
|
||||||
|
(those come from /root/start_base_services_for_taler_exchange.sh).
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
DO_RESTART=0
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--restart|-r) DO_RESTART=1 ;;
|
||||||
|
--help|-h) usage; exit 0 ;;
|
||||||
|
*) echo "Unknown option: $arg" >&2; usage >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$(id -un)" != "taler-exchange-httpd" ]; then
|
||||||
|
echo "This script must be run as user taler-exchange-httpd" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
CONF=/etc/taler-exchange/taler-exchange.conf
|
||||||
|
LOG_DIR=/var/log/taler-exchange
|
||||||
|
PORT=$(taler-exchange-config -c "$CONF" -s exchange -o PORT 2>/dev/null || echo 9011)
|
||||||
|
|
||||||
|
list_httpd_pids() {
|
||||||
|
ps -eo pid=,stat=,args= 2>/dev/null | while read -r pid stat args; do
|
||||||
|
case "$stat" in Z*) continue ;; esac
|
||||||
|
case "$args" in
|
||||||
|
*start_exchange.sh*) continue ;;
|
||||||
|
esac
|
||||||
|
case "$args" in
|
||||||
|
*taler-exchange-httpd\ *|taler-exchange-httpd\ *|/usr/bin/taler-exchange-httpd\ *)
|
||||||
|
echo "$pid"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done | sort -u
|
||||||
|
}
|
||||||
|
|
||||||
|
kill_httpd() {
|
||||||
|
local pids
|
||||||
|
pids=$(list_httpd_pids | tr '\n' ' ')
|
||||||
|
if [ -z "${pids// }" ]; then
|
||||||
|
echo "No live taler-exchange-httpd processes to stop."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "Stopping PIDs: $pids"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
kill -TERM $pids 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
local left
|
||||||
|
left=$(list_httpd_pids | tr '\n' ' ')
|
||||||
|
if [ -n "${left// }" ]; then
|
||||||
|
echo "SIGKILL remaining: $left"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
kill -KILL $left 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
echo "taler-exchange-httpd stopped."
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$DO_RESTART" -eq 1 ]; then
|
||||||
|
echo "=== restart: kill taler-exchange-httpd ==="
|
||||||
|
kill_httpd
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Start taler-exchange-httpd:"
|
||||||
|
LOG_FILE="$LOG_DIR/taler-exchange-httpd-$(date +%Y-%m-%d).log"
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
touch "$LOG_FILE" 2>/dev/null || true
|
||||||
|
|
||||||
|
if [ "$DO_RESTART" -eq 0 ] && [ -n "$(list_httpd_pids)" ]; then
|
||||||
|
echo "taler-exchange-httpd already running"
|
||||||
|
else
|
||||||
|
nohup taler-exchange-httpd -c "$CONF" -L INFO >>"$LOG_FILE" 2>&1 &
|
||||||
|
disown 2>/dev/null || true
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Live processes:"
|
||||||
|
ps -eo pid,stat,args 2>/dev/null | grep taler-exchange-httpd | grep -v grep | grep -v ' Z ' || true
|
||||||
|
|
||||||
|
if [ -x /usr/local/bin/check_exchange-health.sh ]; then
|
||||||
|
/usr/local/bin/check_exchange-health.sh || exit 1
|
||||||
|
elif [ -x ./check_exchange-health.sh ]; then
|
||||||
|
./check_exchange-health.sh || exit 1
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
43
scripts/taler-exchange/start_wire_helpers.sh
Executable file
43
scripts/taler-exchange/start_wire_helpers.sh
Executable file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Start wire/db helpers only (root, no interactive shell, no systemd).
|
||||||
|
# Uses nohup so helpers survive the launching shell.
|
||||||
|
set -euo pipefail
|
||||||
|
ROOT=$(cd "$(dirname "$0")" && pwd)
|
||||||
|
if [ -x "$ROOT/ensure_exchange_helpers.sh" ]; then
|
||||||
|
exec "$ROOT/ensure_exchange_helpers.sh"
|
||||||
|
fi
|
||||||
|
if [ -x /usr/local/bin/ensure_exchange_helpers.sh ]; then
|
||||||
|
exec /usr/local/bin/ensure_exchange_helpers.sh
|
||||||
|
fi
|
||||||
|
# Fallback if ensure not installed yet
|
||||||
|
CONF=/etc/taler-exchange/taler-exchange.conf
|
||||||
|
LOG_DIR=/var/log/taler-exchange
|
||||||
|
[ "$(id -u)" -eq 0 ] || { echo "root only"; exit 1; }
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
|
start_bg() {
|
||||||
|
local user="$1"; shift
|
||||||
|
local name="$1"; shift
|
||||||
|
local bin="$1"
|
||||||
|
if pgrep -u "$user" -x "$(basename "$bin")" >/dev/null 2>&1; then
|
||||||
|
echo "already: $name"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "start: $name as $user"
|
||||||
|
nohup runuser -u "$user" -- "$@" >>"$LOG_DIR/${name}.log" 2>&1 </dev/null &
|
||||||
|
disown 2>/dev/null || true
|
||||||
|
sleep 0.4
|
||||||
|
}
|
||||||
|
|
||||||
|
start_bg taler-exchange-aggregator taler-exchange-aggregator \
|
||||||
|
/usr/bin/taler-exchange-aggregator -c "$CONF" -L INFO
|
||||||
|
start_bg taler-exchange-closer taler-exchange-closer \
|
||||||
|
/usr/bin/taler-exchange-closer -c "$CONF" -L INFO
|
||||||
|
start_bg taler-exchange-wire taler-exchange-wirewatch \
|
||||||
|
/usr/bin/taler-exchange-wirewatch -c "$CONF" -L INFO
|
||||||
|
start_bg taler-exchange-wire taler-exchange-transfer \
|
||||||
|
/usr/bin/taler-exchange-transfer -c "$CONF" -L INFO
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
pgrep -af 'taler-exchange-(aggregator|closer|wirewatch|transfer|httpd|secmod)' || true
|
||||||
|
[ -x /usr/local/bin/check_exchange-health.sh ] && /usr/local/bin/check_exchange-health.sh || true
|
||||||
91
scripts/taler-exchange/wire-enable-and-upload.sh
Executable file
91
scripts/taler-exchange/wire-enable-and-upload.sh
Executable file
|
|
@ -0,0 +1,91 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# One-shot: offline enable wire account + fees, upload to local exchange, verify /keys.
|
||||||
|
# Run as root inside container taler-exchange-hacktivism.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CONF=/etc/taler-exchange/taler-exchange.conf
|
||||||
|
OV=/etc/taler-exchange/exchange-overrides.conf
|
||||||
|
PAYTO='payto://x-taler-bank/bank.hacktivism.ch/exchange?receiver-name=GOA%20Exchange'
|
||||||
|
LOCAL_BASE='http://127.0.0.1:9011/'
|
||||||
|
OPS=/tmp/offline-wire-ops-$$.json
|
||||||
|
OFFLINE_USER=taler-exchange-offline
|
||||||
|
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
echo "Run as root in exchange container" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== 1. Ensure wire account stanza in exchange-overrides ==="
|
||||||
|
if ! grep -q '\[exchange-account-1\]' "$OV" 2>/dev/null; then
|
||||||
|
cat >>"$OV" <<'EOF'
|
||||||
|
|
||||||
|
### Regional bank (libeufin, x-taler-bank) — no IBAN
|
||||||
|
[exchange-account-1]
|
||||||
|
PAYTO_URI = payto://x-taler-bank/bank.hacktivism.ch/exchange?receiver-name=GOA%20Exchange
|
||||||
|
ENABLE_CREDIT = YES
|
||||||
|
ENABLE_DEBIT = YES
|
||||||
|
@inline-secret@ exchange-accountcredentials-1 ../secrets/exchange-accountcredentials-1.secret.conf
|
||||||
|
EOF
|
||||||
|
echo "appended exchange-account-1"
|
||||||
|
else
|
||||||
|
echo "exchange-account-1 already present"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# credentials must be readable by wire helpers + httpd
|
||||||
|
if [ -f /etc/taler-exchange/secrets/exchange-accountcredentials-1.secret.conf ]; then
|
||||||
|
chown root:taler-exchange-wire /etc/taler-exchange/secrets/exchange-accountcredentials-1.secret.conf 2>/dev/null \
|
||||||
|
|| chown root:root /etc/taler-exchange/secrets/exchange-accountcredentials-1.secret.conf
|
||||||
|
chmod 640 /etc/taler-exchange/secrets/exchange-accountcredentials-1.secret.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== 2. Point BASE_URL at local httpd for offline upload ==="
|
||||||
|
# save public URL
|
||||||
|
PUBLIC_BASE=$(taler-config -c "$CONF" -s exchange -o BASE_URL 2>/dev/null || echo 'https://exchange.hacktivism.ch/')
|
||||||
|
# temporary override file (highest priority if inlined last — patch OV)
|
||||||
|
if grep -q '^BASE_URL' "$OV"; then
|
||||||
|
sed -i "s|^BASE_URL = .*|BASE_URL = ${LOCAL_BASE}|" "$OV"
|
||||||
|
else
|
||||||
|
echo "BASE_URL = ${LOCAL_BASE}" >>"$OV"
|
||||||
|
fi
|
||||||
|
echo "BASE_URL now: $(taler-config -c "$CONF" -s exchange -o BASE_URL)"
|
||||||
|
|
||||||
|
echo "=== 3. Sign enable-account + wire-fee + global-fee (as offline user) ==="
|
||||||
|
# global-fee: year, history, account, purse, purse_timeout, history_expiration, max_free_purses
|
||||||
|
runuser -u "$OFFLINE_USER" -- taler-exchange-offline -c "$CONF" \
|
||||||
|
enable-account "$PAYTO" \
|
||||||
|
wire-fee now x-taler-bank GOA:0 GOA:0 \
|
||||||
|
global-fee now GOA:0 GOA:0 GOA:0 '1 day' '1 year' 5 \
|
||||||
|
>"$OPS"
|
||||||
|
echo "ops bytes: $(wc -c <"$OPS")"
|
||||||
|
head -c 200 "$OPS"; echo
|
||||||
|
|
||||||
|
echo "=== 4. Upload ops to exchange ==="
|
||||||
|
runuser -u "$OFFLINE_USER" -- taler-exchange-offline -c "$CONF" upload <"$OPS"
|
||||||
|
echo "upload exit: $?"
|
||||||
|
|
||||||
|
echo "=== 5. Restore public BASE_URL ==="
|
||||||
|
sed -i "s|^BASE_URL = .*|BASE_URL = ${PUBLIC_BASE}|" "$OV"
|
||||||
|
# ensure trailing slash style
|
||||||
|
if ! grep -q "BASE_URL = https://exchange.hacktivism.ch" "$OV"; then
|
||||||
|
sed -i "s|^BASE_URL = .*|BASE_URL = https://exchange.hacktivism.ch/|" "$OV"
|
||||||
|
fi
|
||||||
|
echo "BASE_URL restored: $(taler-config -c "$CONF" -s exchange -o BASE_URL)"
|
||||||
|
|
||||||
|
echo "=== 6. Probe /keys (may need httpd already running) ==="
|
||||||
|
for i in 1 2 3 4 5; do
|
||||||
|
code=$(curl -sS -m 8 -o /tmp/keys-out.json -w '%{http_code}' http://127.0.0.1:9011/keys || echo fail)
|
||||||
|
sz=$(wc -c </tmp/keys-out.json 2>/dev/null || echo 0)
|
||||||
|
echo "try $i: http=$code size=$sz"
|
||||||
|
if [ "$code" = "200" ] && [ "${sz:-0}" -gt 100 ]; then
|
||||||
|
echo "KEYS_OK"
|
||||||
|
head -c 250 /tmp/keys-out.json; echo
|
||||||
|
# show accounts if present
|
||||||
|
grep -oE '"payto_uri"[^,}]+|"master_public_key"[^,}]+' /tmp/keys-out.json | head -10 || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "KEYS_NOT_YET — check logs"
|
||||||
|
tail -30 /var/log/taler-exchange/taler-exchange-httpd-*.log 2>/dev/null | tail -30
|
||||||
|
exit 1
|
||||||
Loading…
Add table
Add a link
Reference in a new issue