scripts: write the dev config on first start

This commit is contained in:
shum committed 2026-10-27 13:04:22 +00:00
1 parent f2322e5949
commit 2e19012e1a
3 files changed
+139 -27

No files matched your search

+42 -14
View File
@@ -441,22 +441,39 @@ each domain to its own port, as the all-in-one example in [Caddy](#caddy) does.
on its first start. Its state is kept in `./data/chain`, so restarts keep the contracts, balances
and registered names. Its keys are anvil's public test keys, so never use it beside a real chain.
- `postgres`: PostgreSQL 17 on `127.0.0.1:5433`, user `simplex`, database `store_service`, without a
password, kept in `./data/postgres`.
password, kept in `./data/postgres`. The service uses it in place of `BADGE_DB_CONN`.
From `scripts/store-service/`:
From a fresh clone:
```
echo "COMPOSE_FILE=compose.yml:compose.dev.yml" >> .env
echo "BADGE_DB_CONN=postgresql://simplex@127.0.0.1:5433/store_service" >> .env
git clone https://github.com/simplex-chat/simplex-chat && cd simplex-chat
git checkout sh/store-service && git submodule update --init apps/simplex-domains
cd scripts/store-service
echo "COMPOSE_FILE=compose.yml:compose.dev.yml" > .env
docker compose up -d --build
docker compose logs chain
```
The service starts once the chain is up. The chain's log prints its `[chain]` section; put it in
`config/store_service.ini` with a `[names]` section and, under `[listener]`,
`names_export_dir = /srv/names-export` (the names build is the image's `/srv/names`, the default),
then `docker compose restart store-service`. With `serve_webapp = on`, the names site is on
`names_port`, by default 8081.
The names site is then on `http://127.0.0.1:8081` and the badges site on `http://127.0.0.1:8080`.
On its first start, the chain writes `config/store_service.ini` for its deployment, unless the file
exists; it never rewrites it, so edits there are kept. The file serves both sites all in one, with
`[names]` on the `.simplex` TLD, `[chain]` at the local chain with 1 confirmation, and `[issuer]`
signing with a public test key at index 999, which no client trusts, through `dev_keys`. That key is
in `dev-chain.sh`, as public as anvil's: never use it elsewhere. The service starts once the chain
and the database are healthy. `USER_UID` and `USER_GID` in `.env` (by default 1000) own the file,
mode 600, and its folder, mode 700.
Names are paid for with prepaid codes, so no payment provider is needed. To issue one, stop the
service and run its console against the dev database:
```
docker compose stop store-service
docker compose run --rm store-service -d postgresql://simplex@127.0.0.1:5433/store_service --run-cli --service-config /etc/simplex-store-service/store_service.ini
```
There, `//issue name 6` prints a code for one name of 6 letters or more (see
[From the command line](#from-the-command-line)). Leave with `/quit`, then
`docker compose start store-service`.
The service key's account starts with 10,000 ETH and a sponsor allowance. To top it up, or set any
account's balance:
@@ -465,10 +482,21 @@ account's balance:
docker compose exec chain dev-chain.sh topup [address] [eth]
```
Registrations wait 10 seconds after their commit (`MIN_COMMITMENT_AGE` in `compose.dev.yml`), and
prepaid codes need no payment provider. To start over, run `docker compose down` and delete
`./data/chain` and `./data/postgres` together; deleting only the chain leaves orders that point at
names that no longer exist.
Registrations wait 10 seconds after their commit (`MIN_COMMITMENT_AGE` in `compose.dev.yml`).
Card payments in Stripe's test mode: uncomment `[stripe]` in `config/store_service.ini` (as the
`USER_UID` user, or with `sudo`), put in the test keys and the webhook secret, which
`stripe listen --forward-to 127.0.0.1:8080/webhooks/stripe` prints, and run
`docker compose restart store-service`. With `dev_keys`, the service refuses live keys, and a
BTCPay that is not on loopback.
To start over, delete the containers and every dev state together, since orders in the database
point at names on the chain. `./data` belongs to root and to Postgres's user, so:
```
docker compose down
sudo rm -rf data config
```
### Caddy
+18 -1
View File
@@ -1,4 +1,5 @@
# Development: compose.yml plus a local chain with the names contracts, kept in ./data/chain across restarts.
# Development: compose.yml plus a local chain with the names contracts, kept in ./data/chain across restarts, which
# writes ./config/store_service.ini for them on its first start, and a local database.
# Enable it with COMPOSE_FILE=compose.yml:compose.dev.yml in .env; unlike a compose.override.yml, it is never
# picked up on its own.
services:
@@ -14,8 +15,12 @@ services:
environment:
# seconds a registration waits after its commit; the contracts' production value is 60
MIN_COMMITMENT_AGE: "10"
# the owner of the config it writes, the store service's user
USER_UID: ${USER_UID:-1000}
USER_GID: ${USER_GID:-1000}
volumes:
- ./data/chain:/chain
- ./config:/config
- ./dev-chain.sh:/usr/local/bin/dev-chain.sh:ro
command: dev-chain.sh
healthcheck:
@@ -43,7 +48,19 @@ services:
retries: 30
start_period: 10s
# compose replaces a command whole, so this is compose.yml's with the dev database in place of BADGE_DB_CONN
store-service:
command:
- "-d"
- "postgresql://simplex@127.0.0.1:5433/store_service"
- "--create-schema"
- "--yes-migrate"
- "--service-config"
- "/etc/simplex-store-service/store_service.ini"
volumes:
# compose creates every container before it starts any, so compose.yml's create_host_path: false would refuse a
# first start before the chain writes ./config; this entry replaces that one by its target
- ./config:/etc/simplex-store-service:ro
depends_on:
chain: { condition: service_healthy }
postgres: { condition: service_healthy }
+79 -12
View File
@@ -1,7 +1,8 @@
#!/bin/sh
# The local chain of compose.dev.yml. Runs in the webapp's dev image, which has anvil, node, the deploy script and the
# compiled contracts.
# dev-chain.sh anvil with its state kept in $CHAIN_DIR, and the names contracts deployed on the first start
# dev-chain.sh anvil with its state kept in $CHAIN_DIR, the names contracts deployed on the first start,
# and $CONFIG_DIR/store_service.ini written for them unless it exists
# dev-chain.sh topup [address] [eth] sets an account's balance, by default the service key's account to 10000 ETH
set -eu
@@ -11,6 +12,17 @@ ANVIL="${ANVIL:-anvil}"
WEBAPP_DIR="${WEBAPP_DIR:-/repo/webapp}"
RPC_URL="http://127.0.0.1:$RPC_PORT"
DEPLOYMENT="$CHAIN_DIR/deployment.json"
CONFIG_DIR="${CONFIG_DIR:-/config}"
CONFIG="$CONFIG_DIR/store_service.ini"
# the store service's user, which must own its config
USER_UID="${USER_UID:-1000}"
USER_GID="${USER_GID:-1000}"
# A public test key, like anvil's: made once with `simplex-chat badge keygen`. The service trusts it only through
# [issuer] dev_keys, which it accepts only on chain 31337, and refuses it at an index clients trust (1 to 8).
DEV_ISSUER_INDEX=999
DEV_ISSUER_SECRET=Grc_c1bKCSa3U8mMwRy6XNTJNwSveJi332wAqyyCy2o=
TERMS_VERSION=2026-10-23
TERMS_URL=https://simplex.chat/
# compose's healthcheck waits for this file, written once the contracts are on the running chain
READY="$CHAIN_DIR/ready"
# the dumps are taken this often and on exit, so a restart keeps the contracts and every name registered on them
@@ -50,17 +62,72 @@ else
(cd "$WEBAPP_DIR" && RPC_URL="$RPC_URL" LOCAL_CHAIN_OUT="$DEPLOYMENT" node dev/deploy.ts)
fi
node -e '
const d = require(process.argv[1])
console.log(`[chain] for config/store_service.ini:
rpc_url = ${d.rpcUrl}
chain_id = ${d.chainId}
controller = ${d.controller}
sponsor = ${d.sponsor}
base_registrar = ${d.baseRegistrar}
resolver = ${d.resolver}
service_key = ${d.registrarKey}
confirmations = 1`)' "$DEPLOYMENT"
field() {
node -p "require('$DEPLOYMENT').$1"
}
write_config() {
tmp="$CONFIG.tmp"
rm -f "$tmp"
(umask 077 && cat > "$tmp" <<INI)
; written by dev-chain.sh for the local chain on its first start, and never rewritten
[listener]
host = 127.0.0.1
badges_port = 8080
names_port = 8081
serve_webapp = on
trust_forwarded_for = on
[poll]
waiting_seconds = 3
idle_seconds = 60
[issuer]
index = $DEV_ISSUER_INDEX
private_key = $DEV_ISSUER_SECRET
dev_keys = $DEV_ISSUER_INDEX:$DEV_ISSUER_SECRET
[names]
tld = $(field tld)
terms_version = $TERMS_VERSION
terms_url = $TERMS_URL
[chain]
rpc_url = $(field rpcUrl)
chain_id = $(field chainId)
controller = $(field controller)
sponsor = $(field sponsor)
base_registrar = $(field baseRegistrar)
resolver = $(field resolver)
service_key = $(field registrarKey)
confirmations = 1
[dev]
accept_unverified_store_receipts = off
; dev_keys accepts only Stripe test keys: sk_test_ or rk_test_, and pk_test_
;[stripe]
;secret_key = rk_test_replace-me
;publishable_key = pk_test_replace-me
;webhook_secret = whsec_replace-me
; dev_keys accepts only a BTCPay on loopback: 127.0.0.1, ::1 or localhost
;[btcpay]
;host = https://127.0.0.1
;api_key = replace-me
;store_id = replace-me
;webhook_secret = replace-me
INI
chown "$USER_UID:$USER_GID" "$CONFIG_DIR" "$tmp"
chmod 700 "$CONFIG_DIR"
mv "$tmp" "$CONFIG"
echo "wrote $CONFIG"
}
if [ -e "$CONFIG" ]; then
echo "kept $CONFIG"
else
write_config
fi
touch "$READY"
wait "$anvil_pid"