Running QORel next to a validator
Validators often relay the channels of their own chain. QORel can run on the validator host, as a sidecar container, or in Kubernetes. This page gives the three layouts and the rules that keep the relayer isolated from the validator's own keys. It is for validator and node operators. For running the node itself see Running a Validator and Running a Node.
Relaying is testnet only today: QORel has been run against qorechain-diana, and no mainnet IBC channel is open.
Innovations
- A hardened service in the package. The
.deband.rpminstall aqorel.servicethat runs as its ownqoreluser, with a0077umask, no new privileges, a private/tmp, a read-only file system outside/var/lib/qorel, and no core dumps. - Keys only in memory, if you want. The Kubernetes layout rebuilds the keys at pod start from a secret into a memory-backed volume, so key files never touch disk.
- Owner-only key files. Key files, including the post-quantum seed, are mode 0600.
- Checks you can alert on.
qorel keys pqc-statusreportsready_to_relay, and the pre-send check stops a transaction that would be refused before a fee is spent.
How to use
Ground rules
- Use a dedicated relayer account. Never the validator operator key and never the consensus key. Fund it with what the relayer needs for fees.
- One relayer process per relayer key. Two processes signing with the same key fight over account sequences.
- Relay only your channels. Set a
packet_filter. - Point QORel at the local node. Use
http://127.0.0.1:26657,http://127.0.0.1:9090andws://127.0.0.1:26657/websocket, and keep those ports closed to the internet. This also gives the relayer the gRPC endpoint that is not available publicly. - On QoreChain, register the relayer's post-quantum key once with
qorel keys register-pqc, and checkqorel keys pqc-statusbefore starting.
1. systemd on the validator host
-
Install the
.debor.rpmpackage (Install). It creates aqorelsystem user, separate from the validator's user, and a hardenedqorel.service. -
Edit
/etc/qorel/config.tomlwith the local node endpoints. -
Add the relayer key as user
qorel, and register the post-quantum key:sudo -u qorel qorel --config /etc/qorel/config.toml keys add --chain qorechain-diana --key-name relayer --mnemonic-file <file>sudo -u qorel qorel --config /etc/qorel/config.toml keys register-pqc --chain qorechain-dianasudo -u qorel qorel --config /etc/qorel/config.toml keys pqc-status --chain qorechain-diana -
Run
systemctl enable --now qorel. -
Give QORel lower priority than the node, so it never competes with block production:
# /etc/systemd/system/qorel.service.d/priority.conf[Service]Nice=10CPUWeight=20MemoryMax=1GThen
systemctl daemon-reload && systemctl restart qorel.
2. Docker Compose sidecar
services:
qorel:
image: ghcr.io/qorechain/qorel:0.1.0
command: ["--config", "/home/nonroot/.hermes/config.toml", "start"]
network_mode: host # reach the node on 127.0.0.1
restart: unless-stopped
volumes:
- ./qorel:/home/nonroot/.hermes # config.toml + keys/ (owner uid 65532, mode 0700)
deploy:
resources:
limits: { cpus: "1.0", memory: 1g }
Add the keys once with the same image, for example:
docker run --rm -v $PWD/qorel:/home/nonroot/.hermes ghcr.io/qorechain/qorel:0.1.0 \
keys add --chain qorechain-diana --key-name relayer --mnemonic-file /home/nonroot/.hermes/relayer.mnemonic
docker run --rm --network host -v $PWD/qorel:/home/nonroot/.hermes ghcr.io/qorechain/qorel:0.1.0 \
keys register-pqc --chain qorechain-diana
Delete the mnemonic file afterwards.
3. Kubernetes
Keep the mnemonic in your secret store and rebuild the keys at start:
- An init container runs
qorel keys addinto anemptyDirwithmedium: Memory(register the post-quantum key once, by hand, beforehand). - The main container runs
qorel starton the same volume.
That way the keys exist only in memory.
apiVersion: apps/v1
kind: Deployment
metadata: { name: qorel }
spec:
replicas: 1 # never more than one per key
strategy: { type: Recreate }
selector: { matchLabels: { app: qorel } }
template:
metadata: { labels: { app: qorel } }
spec:
securityContext: { runAsNonRoot: true, runAsUser: 65532, fsGroup: 65532 }
volumes:
- name: home
emptyDir: { medium: Memory }
- name: config
configMap: { name: qorel-config }
- name: mnemonic
secret: { secretName: qorel-relayer-mnemonic } # key: mnemonic
initContainers:
- name: keys
image: ghcr.io/qorechain/qorel:0.1.0
args: ["--config", "/config/config.toml", "keys", "add", "--chain", "qorechain-diana",
"--key-name", "relayer", "--mnemonic-file", "/secret/mnemonic", "--overwrite"]
volumeMounts:
- { name: home, mountPath: /home/nonroot/.hermes }
- { name: config, mountPath: /config }
- { name: mnemonic, mountPath: /secret, readOnly: true }
# repeat the init container for each chain in the config
containers:
- name: qorel
image: ghcr.io/qorechain/qorel:0.1.0
args: ["--config", "/config/config.toml", "start"]
ports: [{ containerPort: 3001, name: telemetry }]
resources: { limits: { cpu: "1", memory: 1Gi } }
volumeMounts:
- { name: home, mountPath: /home/nonroot/.hermes }
- { name: config, mountPath: /config }
The config's key_store_folder must point at /home/nonroot/.hermes/keys (or be left unset).
Monitoring
Enable telemetry and alert on pending packets, relayer balances, the post-quantum key state and client freshness. The list is on Monitoring.
How to access
- Network. Testnet
qorechain-diana. The relayer connects to your own node's local ports and to the other chain's endpoints. - Accounts. A dedicated relayer account on each chain, funded for fees; never the validator operator key.
- Host. Linux with systemd for layout 1; Docker with host networking for layout 2; a cluster with a memory-backed
emptyDirfor layout 3. - Cost. Fees only. The examples above cap the relayer at 1 CPU and 1 GiB of memory.
Where it is published
The packages, the container image and the source are listed on Install. The example config is packaging/config.example.toml in qorechain/QORel.
Limits and known issues
- Not a validator duty. Relaying is optional and separate from validating; a stopped relayer does not affect consensus.
- One process per key. Rolling updates that start a second pod on the same key break the account sequence; the example uses
Recreate. - Manual registration.
keys register-pqcis a one-time manual step; the Kubernetes init container only rebuilds the keys. - Testnet only. There is no mainnet channel to relay yet.