# Taler Exchange Setup Main documentation: https://docs.taler.net/taler-exchange-manual.html ## Installation `# apt install taler-exchange` ## Configuration Given `BASE_URL=exchange.bookseller.taler.net`... ### Database ``` # apt install taler-exchange-database # (if not there already) # taler-exchange-dbconfig # sudo -u taler-exchange-httpd taler-exchange-dbinit ``` ### Reverse Proxy `# apt install caddy` `/etc/caddy/Caddyfile` should contain: ``` # Debian taler-exchange exchange.bookseller.taler.net { reverse_proxy unix//run/taler-exchange/httpd/exchange-http.sock } ``` ### Coin Denominations Use coins' _code_, not _name_. `taler-harness deployment gen-coin-config --min-amount BKZ:0.01 --max-amount BKZ:100 > /etc/taler-exchange/conf.d/exchange-coins.conf` BUG: you need to fix the generated `exchange-coins.conf`: `sed -i -e 's/COIN_/coin_/g' /etc/taler-exchange/conf.d/exchange-coins.conf` `/etc/taler-exchange/conf.d/currencies.conf`: ``` [currency-bookz] ENABLED = YES name = "BOOKZ" code = "BKZ" fractional_input_digits = 2 fractional_normal_digits = 2 fractional_trailing_zero_digits = 2 alt_unit_names = {"0":"📗"} common_amounts = "BKZ:5 BKZ:10 BKZ:25 BKZ:50" ``` Start `taler-exchange`: `systemctl start taler-exchange.target` If something goes wrong, restart from scratch: 1. Stop taler-exchange: `systemctl stop taler-exchange.target` 2. Drop database: `sudo -H -u postgres dropdb 'taler-exchange'` 3. Redo `taler-exchange-dbconfig` 4. Redo coin denominations ### Fee Structure This is run on the offline machine: ``` # apt install taler-exchange-offline # taler-exchange-offline setup ``` Here you get the `MASTER_KEY`. Back online to `/etc/taler-exchange/conf.d/exchange-business.conf`: ``` # Configuration for business-level aspects of the exchange. [exchange] # Here you MUST add the master public key of the offline system # which you can get using `taler-exchange-offline setup`. # This is just an example, your key will be different! # MASTER_PUBLIC_KEY = YE6Q6TR1EDB7FD0S68TGDZGF1P0GHJD2S0XVV8R2S62MYJ6HJ4ZG MASTER_PUBLIC_KEY = $MASTER_KEY # Publicly visible base URL of the exchange. # BASE_URL = https://example.com/ BASE_URL = https://exchange.bookseller.taler.net/ # Here you MUST configure the amount above which transactions are # always subject to manual AML review. AML_THRESHOLD = 10000000 # Attribute encryption key for storing attributes encrypted # in the database. Should be a high-entropy nonce. # Run `openssl rand -hex 32` to obtain a 256 bit nonce ATTRIBUTE_ENCRYPTION_KEY = $(openssl rand -hex 32) # For your terms of service and privacy policy, you should specify # an Etag that must be updated whenever there are significant # changes to either document. The format is up to you, what matters # is that the value is updated and never reused. See the HTTP # specification on Etags. TERMS_DIR = /srv/www/taler.net/bookseller/exchange/ TERMS_ETAG = bookseller-tos-v1 PRIVACY_ETAG = bookseller-prv-v1 # Redirect https://exchange.bookseller.taler.net to this URL TOPLEVEL_REDIRECT_URL = https://bookseller.taler.net/exchange-operator # WARNING Configuration fails to specify option `TINY_AMOUNT' in section `exchange'! TINY_AMOUNT = BOOKZ:0.01 # WARNING Configuration fails to specify option `SHOPPING_URL' in section `exchange'! SHOPPING_URL = https://shop.bookseller.taler.net/ [merchant-exchange-bookseller.taler.net] MASTER_KEY = $MASTER_KEY CURRENCY = BOOKZ EXCHANGE_BASE_URL = https://exchange.bookseller.taler.net/ # Bank accounts used by the exchange should be specified here: [exchange-account-1] # Use for exchange-wirewatch (and listed in /wire) ENABLE_CREDIT = YES # Use for exchange-aggregator (outgoing transfers) ENABLE_DEBIT = YES # Account identifier in the form of an RFC-8905 payto:// URI. # For SEPA, looks like payto://sepa/$IBAN?receiver-name=$NAME # Make sure to URL-encode spaces in $NAME! PAYTO_URI = payto://x-taler-bank/bank.bookseller.taler.net/exchange?receiver-name=TALER%20Bookseller%20Bank #PAYTO_URI = "payto://x-taler-bank/localhost:9099/exchange?receiver-name=TALER%20Bookseller%20Bank" # URL for talking to the bank wire the wire API. WIRE_GATEWAY_URL = https://bank.bookseller.taler.net/accounts/exchange/taler-wire-gateway/ # Credentials to access the account are in a separate # config file with restricted permissions. @inline-secret@ exchange-accountcredentials-1 ../secrets/exchange-accountcredentials-1.secret.conf ``` And the secrets: ``` # This file contains the secret credentials # to access the Taler Wire Gateway API (usually # provided by LibEuFin) for the exchange accounts. # # Each exchange-account-* section should have a matching # exchange-accountcredentials-* section here. # # Each of those sections must be imported via @inline-secret@, # usually in conf.d/exchange-business.conf. [exchange-accountcredentials-1] WIRE_GATEWAY_AUTH_METHOD = bearer TOKEN = secret-token:SOME-SECRET-TOKEN # URL for talking to the bank wire the wire API. WIRE_GATEWAY_URL = https://bank.bookseller.taler.net/accounts/exchange/taler-wire-gateway/ ``` ### Bank Account ### Auditors ### Offline Signing - /var/lib/taler-exchange/offline/master.priv must be readable by taler-exchange-offline Wait for `taler-exchange-secmod-rsa` process to finish setting up keys before running the following commands. This step may take several minutes. On the offline system: ``` $ taler-exchange-offline download > sig-request.json $ taler-exchange-offline sign < sig-request.json > sig-response.json $ taler-exchange-offline enable-account payto://x-taler-bank/bank.bookseller.taler.net/exchange?receiver-name=TALER%20Bookseller%20Bank > acct-response.json $ taler-exchange-offline wire-fee now x-taler-bank BKZ:0 BKZ:0 > fee-response.json $ taler-exchange-offline global-fee now BKZ:0 BKZ:0 BKZ:0 4weeks 6a 4 > global-response.json ``` On the online system: ``` # taler-exchange-offline upload < sig-response.json # taler-exchange-offline upload < acct-response.json # taler-exchange-offline upload < fee-response.json # taler-exchange-offline upload < global-response.json ``` BUG: the last step gives an error: > 2026-02-27T14:05:42.020965+0000 taler-exchange-offline-427284 WARNING External protocol violation detected at json_helper.c:101. > 2026-02-27T14:05:42.021036+0000 taler-exchange-offline-427284 WARNING Expected currency `BOOKZ', but amount used currency `BKZ' in field `history_fee' > 2026-02-27T14:05:42.021049+0000 taler-exchange-offline-427284 ERROR Invalid input to set wire fee: history_fee#0 at 0 (skipping) #### Signing the offline keys Then, generate future keys from the offline system: ``` $ taler-exchange-offline download > future-keys.json $ taler-exchange-offline show < future-keys.json ``` This should show a long file with all coin denominations for this Exchange. Once ready, ``` $ taler-exchange-offline sign < future-keys.json > offline-sigs.json $ taler-exchange-offline upload < offline-sigs.json ``` Restart the Exchange service! ### Terms of Service ## Test Browse to https://$BASE_URL/management/keys # TODO - [ ] How to generate secrests in Fee Structure? - [ ] Bank Account - [ ] Auditors (optional) - [ ] ToS generation