summaryrefslogtreecommitdiff
path: root/taler-exchange-manual.rst
diff options
context:
space:
mode:
Diffstat (limited to 'taler-exchange-manual.rst')
-rw-r--r--taler-exchange-manual.rst935
1 files changed, 921 insertions, 14 deletions
diff --git a/taler-exchange-manual.rst b/taler-exchange-manual.rst
index 1604d49f..3b06fe7e 100644
--- a/taler-exchange-manual.rst
+++ b/taler-exchange-manual.rst
@@ -1,7 +1,7 @@
..
This file is part of GNU TALER.
- Copyright (C) 2014-2020 Taler Systems SA
+ Copyright (C) 2014-2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software
@@ -15,6 +15,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
@author Christian Grothoff
+ @author Florian Dold
GNU Taler Exchange Operator Manual
##################################
@@ -46,7 +47,7 @@ offering regular currencies today.
About this manual
-----------------
-This tutorial targets system administrators who want to install and
+This manual targets system administrators who want to install and
operate a GNU Taler exchange.
Organizational prerequisites
@@ -289,6 +290,35 @@ Before installing a Taler exchange, please make sure that your
system does not have swap space enabled. Swap space is a security
risk that Taler does not try to mitigate against.
+We recommend the setup of offline signing keys to be done on a second machine that
+does not have Internet access.
+
+In this guide's shell-session fragments, the command prompt shows two pieces
+of information:
+
+* Who is performing the command
+ (``$user`` vs ``root``, and ending character ``$`` vs ``#``).
+* Host where the command is supposed to be executed
+ (``exchange-offline`` vs ``exchange-online``).
+ It is possible to do the entire setup on one machine,
+ but we do not recommend this for security reasons.
+
+Before you start
+----------------
+
+To deploy this with a real bank, you need:
+
+ * IBAN of the bank account to use
+ * BIC of the bank
+ * EBICS host, user and partner IDs
+
+Information to write down during the installation:
+
+ * LibEuFin Nexus superuser password
+ * Taler facade base URL
+ * exchange Nexus username and password
+
+
Installing from source
----------------------
@@ -333,9 +363,9 @@ Installing the GNU Taler binary packages on Debian
To install the Taler exchange, you can now simply run:
-.. code-block:: console
+.. code-block:: shell-session
- # apt install taler-exchange
+ [root@exchange-online]# apt install taler-exchange
Note that the package does not perform any configuration work except for
setting up the various users and the systemd service scripts. You still must
@@ -343,8 +373,12 @@ configure at least the database, HTTP reverse proxy (typically with TLS
certificates), denomination and fee structure, bank account, auditor(s),
offline signing and the terms of service.
-Sample configuration files for the HTTP reverse proxy can be found in
-``/etc/taler-exchange/``.
+On the offline system, you should run at least:
+
+.. code-block:: shell-session
+
+ [root@exchange-offline]# apt install taler-exchange-offline
+
Installing the GNU Taler binary packages on Trisquel
----------------------------------------------------
@@ -358,9 +392,9 @@ Installing the GNU Taler binary packages on Ubuntu
To install the Taler exchange, you can now simply run:
-.. code-block:: console
+.. code-block:: shell-session
- # apt install taler-exchange
+ [root@exchange-online]# apt install taler-exchange
Note that the package does not perform any configuration work except for
setting up the various users and the systemd service scripts. You still must
@@ -368,16 +402,873 @@ configure at least the database, HTTP reverse proxy (typically with TLS
certificates), denomination and fee structure, bank account, auditor(s),
offline signing and the terms of service.
-Sample configuration files for the HTTP reverse proxy can be found in
-``/etc/taler-exchange/``.
+On the offline system, you should run at least:
+.. code-block:: shell-session
-Configuration
+ [root@exchange-offline]# apt install taler-exchange-offline
+
+
+Services, users, groups and file system hierarchy
+-------------------------------------------------
+
+The *taler-exchange* package will create several system users
+to compartmentalize different parts of the system:
+
+* ``taler-exchange-httpd``: runs the HTTP daemon with the core business logic.
+* ``taler-exchange-secmod-rsa``: manages the RSA private online signing keys.
+* ``taler-exchange-secmod-eddsa``: manages the EdDSA private online signing keys.
+* ``taler-exchange-closer``: closes idle reserves by triggering wire transfers that refund the originator.
+* ``taler-exchange-aggregator``: aggregates deposits into larger wire transfer requests.
+* ``taler-exchange-wire``: performs wire transfers with the bank (via LibEuFin/Nexus).
+* ``postgres``: runs the PostgreSQL database (from *postgresql* package).
+* ``www-data``: runs the frontend HTTPS service with the TLS keys (from *nginx* package).
+
+.. note::
+
+ The *taler-merchant* package additionally creates a ``taler-merchant-httpd`` user
+ to run the HTTP daemon with the merchant business logic.
+
+
+The exchange setup uses the following system groups:
+
+* ``taler-exchange-db``: group for all Taler users with direct database access, specifically taler-exchange-httpd, taler-exchange-wire, taler-exchange-closer and taler-exchange-aggregator.
+* ``taler-exchange-secmod``: group for processes with access to online signing keys; this group must have three users: taler-exchange-secmod-rsa, taler-exchange-secmod-eddsa and taler-exchange-httpd.
+* ``taler-exchange-offline``: group for the access to the offline private key (only used on the offline host and not used on the online system).
+
+
+
+The package will deploy systemd service files in
+``/usr/lib/systemd/system/`` for the various components:
+
+* ``taler-exchange-aggregator.service``: service that schedules wire transfers
+ which combine multiple deposits to the same merchant.
+* ``taler-exchange-closer.service``: service that watches for reserves that have been abandoned and schedules wire transfers to send the money back to the originator.
+* ``taler-exchange-httpd.service``: main Taler exchange logic with the public REST API.
+* ``taler-exchange-httpd.socket``: systemd socket activation for the Taler exchange HTTP daemon.
+* ``taler-exchange-secmod-eddsa.service``: software security module for making EdDSA signatures.
+* ``taler-exchange-secmod-rsa.service``: software security module for making RSA signatures.
+* ``taler-exchange-secmod-cs.service``: software security module for making CS signatures.
+* ``taler-exchange-transfer.service``: service that triggers outgoing wire transfers (pays merchants).
+* ``taler-exchange-wirewatch.service``: service that watches for incoming wire transfers (first step of withdraw).
+* ``taler-exchange.target``: Main target for the Taler exchange to be operational.
+
+
+The deployment creates the following key locations in the system:
+
+* ``/etc/taler/``: configuration files.
+* ``/run/taler/``: contains the UNIX domain sockets for inter-process communication (IPC).
+* ``/var/lib/taler/``: serves as the $HOME for all Taler users and contains sub-directories
+ with the private keys; which keys are stored here depends on the host:
+
+ * online system: exchange-secmod-eddsa and exchange-secmod-rsa keys.
+ * offline system: exchange-offline keys.
+
+
+Exchange Database Setup
+=======================
+
+The access credentials for the exchange's database are configured in
+``/etc/taler/secrets/exchange-db.secret.conf``. Currently, only PostgreSQL is
+supported as a database backend.
+
+The following users must have access to the exchange database:
+
+* taler-exchange-httpd
+* taler-exchange-wire
+* taler-exchange-aggregator
+* taler-exchange-closer
+
+These users are all in the taler-exchange-db group, and the
+``exchange-db.secret.conf`` should already be only readable by users in
+this group.
+
+To create a database for the Taler exchange on the local system, run:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# su - postgres
+ [postgres@exchange-online]# createuser taler-exchange-httpd
+ [postgres@exchange-online]# createuser taler-exchange-wire
+ [postgres@exchange-online]# createuser taler-exchange-aggregator
+ [postgres@exchange-online]# createuser taler-exchange-closer
+ [postgres@exchange-online]# createdb -O taler-exchange-httpd taler-exchange
+ [postgres@exchange-online]# exit
+
+This will create a ``taler-exchange`` database owned by the
+``taler-exchange-httpd`` user. We will use that user later to perform
+database maintenance operations.
+
+
+Assuming the above database setup, the database credentials to configure
+in the configuration file would simply be:
+
+.. code-block:: ini
+ :caption: /etc/taler/secrets/exchange-db.secret.conf
+
+ [exchangedb-postgres]
+ CONFIG=postgres:///taler-exchange
+
+
+If the database is run on a different host, please follow the instructions
+from the PostgreSQL manual for configuring remote access.
+
+After configuring the database credentials, the exchange database needs
+to be initialized with the following command:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# sudo -u taler-exchange-httpd taler-exchange-dbinit
+
+Finally we need to grant the other accounts limited access:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# sudo -u taler-exchange-httpd bash
+ [taler-exchange-httpd@exchange-online]# echo 'GRANT SELECT,INSERT,UPDATE ON ALL TABLES IN SCHEMA public TO "taler-exchange-aggregator";' \
+ | psql taler-exchange
+ [taler-exchange-httpd@exchange-online]# echo 'GRANT SELECT,INSERT,UPDATE ON ALL TABLES IN SCHEMA public TO "taler-exchange-closer";' \
+ | psql taler-exchange
+ [taler-exchange-httpd@exchange-online]# echo 'GRANT SELECT,INSERT,UPDATE ON ALL TABLES IN SCHEMA public TO "taler-exchange-wire";' \
+ | psql taler-exchange
+ [taler-exchange-httpd@exchange-online]# echo 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO "taler-exchange-aggregator";' \
+ | psql taler-exchange
+ [taler-exchange-httpd@exchange-online]# echo 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO "taler-exchange-closer";' \
+ | psql taler-exchange
+ [taler-exchange-httpd@exchange-online]# echo 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO "taler-exchange-wire";' \
+ | psql taler-exchange
+ [taler-exchange-httpd@exchange-online]# exit
+
+.. note::
+
+ The above instructions for changing database permissions only work *after*
+ having initialized the database with ``taler-exchange-dbinit``, as
+ the tables to exist before permissions can be granted on them. The
+ ``taler-exchange-dbinit`` tool cannot setup these permissions, as it
+ does not know which users will be used for which processes.
+
+
+Basic Setup: Currency and Denominations
+=======================================
+
+A Taler exchange only supports a single currency. The currency
+and the smallest currency unit supported by the bank system
+must be specified in ``/etc/taler/taler.conf``.
+
+.. code-block:: ini
+ :caption: /etc/taler/taler.conf
+
+ [taler]
+ CURRENCY = EUR
+ CURRENCY_ROUND_UNIT = EUR:0.01
+
+ # ... rest of file ...
+
+.. warning::
+
+ When editing ``/etc/taler/taler.conf``, take care to not accidentally remove
+ the ``@inline-matching@`` directive to include the configuration files in ``conf.d``.
+
+Next, the electronic cash denominations that the exchange offers must be
+specified. The ``taler-wallet-cli`` has a helper command that generates a
+reasonable denomination structure.
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# taler-wallet-cli deployment gen-coin-config \
+ --min-amount EUR:0.01 \
+ --max-amount EUR:100 \
+ > /etc/taler/conf.d/exchange-coins.conf
+
+You can manually review and edit the generated configuration file. The main
+change that is possibly required is updating the various fees.
+
+
+Wire Gateway Setup
+==================
+
+The Taler Wire Gateway is an API that connects the Taler exchange to
+the underlying core banking system.
+
+LibEuFin is an implementation of the Wire Gateway API for the EBICS protocol.
+This section will walk through (1) installing and configuring LibEuFin and
+(2) connecting the Taler Exchange to LibEuFin.
+
+.. note::
+
+ If you do not have a bank account with EBICS but want to test these instructions,
+ you can use the EBICS sandbox as described in the
+ :doc:`LibEuFin Tutorial <libeufin/nexus-tutorial>`.
+
+
+Installation and Basic Configuration
+------------------------------------
+
+First, install the ``libeufin`` package. This can be done on the ``exchange-online``
+machine or a different one.
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# apt-get install -y libeufin
+
+The main component of LibEuFin is called the Nexus. It implements a Web
+service that provides a JSON abstraction layer to access bank accounts.
+
+The HTTP port and database connection string can be edited in the configuration:
+
+.. code-block:: ini
+ :caption: /etc/libeufin/nexus.env
+
+ LIBEUFIN_NEXUS_PORT=5017
+ LIBEUFIN_NEXUS_DB_CONNECTION=jdbc:sqlite:/var/lib/libeufin/nexus/nexus-db.sqlite3
+
+After configuring the database, you can start the service.
+The database is initialized automatically.
+
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# systemctl enable libeufin-nexus
+ [root@exchange-online]# systemctl start libeufin-nexus
+
+You can now create a superuser account. The command to
+create the superuser needs direct database access, thus
+the configuration file is sourced first, and the relevant
+environment variable is exported.
+
+.. code-block:: console
+
+ [root@exchange-online]# source /etc/libeufin/nexus.env
+ [root@exchange-online]# export LIBEUFIN_NEXUS_DB_CONNECTION
+ [root@exchange-online]# NEXUS_ADMIN_PW=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13)
+ [root@exchange-online]# libeufin-nexus superuser admin --password $NEXUS_ADMIN_PW
+
+If you omit ``--password $NEXUS_ADMIN_PW``, you will interactively be asked for a password.
+For simplicity, a superuser can as well act as a normal user, but an API
+to create less privileged users is offered.
+
+.. note::
+
+ User and permissions management in LibEuFin is still under development.
+ In particular, permissions for non-superusers are very limited at the moment.
+
+
+Connecting Nexus with an EBICS account
+--------------------------------------
+
+The command line interface of the LibEuFin Nexus needs the following three
+values to be defined in the environment: ``LIBEUFIN_NEXUS_URL``,
+``LIBEUFIN_NEXUS_USERNAME``, and ``LIBEUFIN_NEXUS_PASSWORD``. In this example,
+``LIBEUFIN_NEXUS_USERNAME`` should be set to ``admin``, and
+``LIBEUFIN_NEXUS_PASSWORD`` to the value hold in ``NEXUS_ADMIN_PW`` from the
+previous step (the ``libeufin-nexus superuser`` command). The
+``LIBEUFIN_NEXUS_URL`` could be given as ``http://localhost:5017/``.
+
+Next, we create a EBICS *bank connection* that Nexus can use to communicate with the bank.
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli \
+ connections \
+ new-ebics-connection \
+ --ebics-url $EBICS_BASE_URL \
+ --host-id $EBICS_HOST_ID \
+ --partner-id $EBICS_PARTNER_ID \
+ --ebics-user-id $EBICS_USER_ID \
+ $CONNECTION_NAME
+
+If this step executes correctly, Nexus will have created all the cryptographic
+material that is needed on the client side; in this EBICS example, it created
+the signature and identification keys. It is therefore advisable to *make
+a backup copy* of such keys.
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli \
+ connections \
+ export-backup \
+ --passphrase $SECRET \
+ --output-file $BACKUP_FILE \
+ $CONNECTION_NAME
+
+At this point, Nexus needs to both communicate its keys to the bank, and
+download the bank's keys. This synchronization happens through the INI, HIA, and
+finally, HPB message types.
+
+After the electronic synchronization, the subscriber must confirm their keys
+by sending a physical mail to the bank. The following command helps generating
+such letter:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli connections get-key-letter $CONNECTION_NAME out.pdf
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli \
+ connections \
+ connect \
+ $CONNECTION_NAME
+
+..
+ FIXME: Maybe is not 100% clear that 'connecting' means exchanging keys
+ with the bank?
+
+Once the connection is synchronized, Nexus needs to import locally the data
+corresponding to the bank accounts offered by the bank connection just made.
+The command below downloads the list of the bank accounts offered by ``$CONNECTION_NAME``.
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli \
+ connections \
+ download-bank-accounts \
+ $CONNECTION_NAME
+
+It is now possible to list the accounts offered by the connection.
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli \
+ connections \
+ list-offered-bank-accounts \
+ $CONNECTION_NAME
+
+.. note::
+
+ The ``nexusBankAccountId`` field should at this step be ``null``,
+ as we have not yet imported the bank account and thus the account
+ does not yet have a local name.
+
+Nexus now needs an explicit import of the accounts it should manage. This
+step is needed to let the user pick a custom name for such accounts.
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli \
+ connections \
+ import-bank-account \
+ --offered-account-id testacct01 \
+ --nexus-bank-account-id $LOCAL_ACCOUNT_NAME \
+ $CONNECTION_NAME
+
+Once a Nexus user imported a bank account (``$LOCAL_ACCOUNT_NAME``)
+under a certain connection (``$CONNECTION_NAME``), it is possible
+to accomplish the usual operations for any bank account: asking for the
+list of transactions, and making a payment.
+
+Testing: Requesting the transaction history
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The LibEuFin Nexus keeps a local copy of the bank account's transaction
+history. Before querying transactions locally, it is necessary
+to request transactions for the bank account via the bank connection.
+
+This command asks Nexus to download the latest transaction reports/statements
+through the bank connection:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli accounts fetch-transactions $LOCAL_ACCOUNT_NAME
+
+.. note::
+
+ By default, the latest available transactions are fetched. It is also
+ possible to specify a custom date range (or even all available transactions)
+ and the type of transactions to fetch (inter-day statements or intra-day
+ reports).
+
+..
+ FIXME: Possibly the date range filter is still missing, see #6243.
+
+Once Nexus has stored all the information in the database, the
+client can ask to actually see the transactions:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli accounts transactions $LOCAL_ACCOUNT_NAME
+
+Testing: Making payments
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Payments pass through two phases: preparation and submission. The preparation
+phase assigns the payment initiation a unique ID, which prevents accidental
+double submissions of payments in case of network failures or other
+disruptions.
+
+
+The following command prepares a payment:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli accounts prepare-payment \
+ --creditor-iban=$IBAN_TO_SEND_MONEY_TO \
+ --creditor-bic=$BIC_TO_SEND_MONEY_TO \
+ --creditor-name=$CREDITOR_NAME \
+ --payment-amount=$AMOUNT \
+ --payment-subject=$SUBJECT \
+ $LOCAL_ACCOUNT_NAME
+
+Note: the ``$AMOUNT`` value needs the format ``X.Y:CURRENCY``; for example
+``EUR:10``, or ``EUR:1.01``.
+
+The previous command should return a value (``$UUID``) that uniquely
+identifies the prepared payment in the Nexus system. That is needed
+in the next step, to **send the payment instructions to the bank**:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli accounts submit-payments \
+ --payment-uuid $UUID \
+ $LOCAL_ACCOUNT_NAME
+
+Automatic scheduling
+~~~~~~~~~~~~~~~~~~~~
+
+With an EBICS bank connection, the LibEuFin Nexus needs to regularly query for
+new transactions and (re-)submit prepared payments.
+
+It is possible to schedule these tasks via an external task scheduler such as
+cron(8). However, the nexus also has an internal task scheduling mechanism for
+accounts.
+
+
+The following three commands create a schedule for submitting payments hourly,
+fetching transactions (intra-day reports) every 5 minutes, and (inter-day statements)
+once at 11pm every day:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \
+ --task-type="submit" \
+ --task-name='submit-payments-hourly' \
+ --task-cronspec='0 0 *'
+
+ [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \
+ --task-type="fetch" \
+ --task-name='fetch-5min' \
+ --task-cronspec='0 */5 *' \
+ --task-param-level=report \
+ --task-param-range-type=latest
+
+ [root@exchange-online]# libeufin-cli accounts task-schedule $LOCAL_ACCOUNT_NAME \
+ --task-type="fetch" \
+ --task-name='fetch-daily' \
+ --task-cronspec='0 0 23' \
+ --task-param-level=statement \
+ --task-param-range-type=latest
+
+The cronspec has the following format, which is slightly non-standard due to
+the ``SECONDS`` field
+
+.. code-block:: none
+
+ SECONDS MINUTES HOURS DAY-OF-MONTH[optional] MONTH[optional] DAY-OF-WEEK[optional]
+
+
+Creating a Taler facade
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Facades are additional abstraction layers that can serve
+specific purposes. For example, one application might need
+a filtered version of the transaction history, or it might
+want to refuse payments that do not conform to certain rules.
+
+At this moment, only the *Taler facade type* is implemented
+in the Nexus, and the command below instantiates one under a
+existing bank account / connection pair. You can freely
+assign an identifier for the ``$FACADE_NAME`` below:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli facades new-taler-wire-gateway-facade \
+ --currency EUR \
+ --facade-name $FACADE_NAME \
+ $CONNECTION_NAME \
+ $LOCAL_ACCOUNT_NAME
+
+At this point, the additional :doc:`taler-wire-gateway API <core/api-wire>`
+becomes offered by the Nexus. The purpose is to let a Taler exchange rely on
+Nexus to manage its bank account.
+
+The base URL of the facade that can be used by the Taler exchange
+as the Taler Wire Gateway base URL can be seen by listing the facades:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli facades list
+
+Managing Permissions and Users
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This guide has so far assumed that a superuser is accessing the LibEuFin Nexus.
+However, it is advisable that the Nexus is accessed with users that only have a
+minimal set of permissions.
+
+The Nexus currently only has support for giving non-superusers access to Taler
+wire gateway facades.
+
+To create a new user, use the ``users`` subcommand of the CLI:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli users list
+ # [ ... shows available users ... ]
+
+ [root@exchange-online]# libeufin-cli users create $USERNAME
+ # [ ... will prompt for password ... ]
+
+Permissions are managed with the ``permissions`` subcommand.
+The following commands grant permissions to view the transaction history
+and create payment initiations with a Taler wire gateway facade:
+
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli permissions grant \
+ user $USERNAME \
+ facade $FACADENAME \
+ facade.talerwiregateway.history
+
+ [root@exchange-online]# libeufin-cli permissions grant \
+ user $USERNAME \
+ facade $FACADENAME \
+ facade.talerwiregateway.transfer
+
+..
+ FIXME: The two commands above output an empty JSON object
+ when successful. Possibly, we should suppress that (just like
+ the other commands do).
+
+The list of all granted permissions can be reviewed:
+
+.. code-block:: console
+
+ [root@exchange-online]# libeufin-cli permissions list
+
+
+Exchange Wire Configuration
+---------------------------
+
+The exchange must be configured with the right settings to
+access the Taler Wire Gateway. An exchange can be configured
+to use multiple bank accounts by using multiple Wire Gateways.
+Typically only one Wire Gateway is used.
+
+A Taler Wire Gateway is configured in a configuration section that follows the
+pattern ``exchange-account-$id``, where ``$id`` is an internal identifier for
+the bank account accessed by the exchange. The basic information for an account should
+be put in ``/etc/taler/conf.d/exchange-business.conf``.
+The secret credentials to access the Taler Wire Gateway API should
+be put into a corresponding ``exchange-accountcredentials-$id`` section
+in ``/etc/taler/secrets/exchange-accountcredentials.conf``.
+The latter file
+should already be only readable for the ``taler-exchange-wire`` user. Other
+exchange processes should not have access to this information.
+
+.. code-block:: ini
+ :caption: /etc/taler/conf.d/exchange-business.conf
+
+ [exchange-account-1]
+ enable_credit = yes
+ enable_debit = yes
+
+ # Account identifier in the form of an RFC-8905 payto:// URI.
+ # For SEPA, looks like payto://iban/$IBAN?receiver-name=$NAME
+ # Make sure to URL-encode spaces in $NAME!
+ payto_uri =
+
+ @inline-secret@ exchange-accountcredentials-1 ../secrets/exchange-accountcredentials.secret.conf
+
+
+.. code-block:: ini
+ :caption: /etc/taler/secrets/exchange-accountcredentials.secret.conf
+
+ [exchange-accountcredentials-1]
+
+ # LibEuFin expects basic auth.
+ wire_gateway_auth_method = basic
+
+ # Username and password set in LibEuFin.
+ username = ...
+ password = ...
+
+ # Base URL of the wire gateway set up with LibEuFin.
+ wire_gateway_url = ...
+
+
+The Wire Gateway configuration can be tested with the following command:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# taler-exchange-wire-gateway-client \
+ --section exchange-accountcredentials-1 --debit-history
+ [root@exchange-online]# taler-exchange-wire-gateway-client \
+ --section exchange-accountcredentials-1 --credit-history
+
+
+Exchange Web service / API Setup
+================================
+
+By default, the ``taler-exchange-httpd`` service listens for HTTP connections
+on a UNIX domain socket. To make the service publicly available, a reverse
+proxy such as nginx should be used. We strongly recommend to configure nginx
+to use TLS.
+
+The public URL that the exchange will be served under should
+be put in ``/etc/taler/conf.d/exchange-business.conf`` configuration file.
+
+.. code-block:: ini
+ :caption: /etc/taler/conf.d/exchange-business.conf
+
+ [exchange]
+ BASE_URL = https://example.com/
+
+ # ... rest of file ...
+
+The ``taler-exchange`` package ships with a sample configuration that can be
+enabled in nginx:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# vim /etc/nginx/sites-available/taler-exchange
+ < ... customize configuration ... >
+ [root@exchange-online]# ln -s /etc/nginx/sites-available/taler-exchange \
+ /etc/nginx/sites-enabled/taler-exchange
+ [root@exchange-online]# systemctl reload nginx
+
+
+The exchange HTTP service can now be started:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# systemctl start taler-exchange.target
+
+
+.. note::
+
+ At this point, the exchange service is not yet fully operational.
+
+
+To check whether the exchange is running correctly under the advertized
+base URL, run:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# export BASE_URL=$(taler-config -s exchange -o base_url)
+ [root@exchange-online]# wget ${BASE_URL}management/keys
+
+The request might take some time to complete on slow machines, because
+a lot of key material will be generated.
+
+
+Offline Signing Setup
+=====================
+
+The offline signing keys of the exchange should be stored on a different machine.
+The responsibilities of this offline signing machine are:
+
+* Generation of the exchange's offline master signing key.
+* Secure storage of the exchange's offline master signing key.
+* Generation of certificates (signed with the offline master signing key) that will be imported by the exchange.
+
+
+.. code-block:: shell-session
+
+ [root@exchange-offline]# sudo -u taler-exchange-offline taler-exchange-offline setup
+ < ... prints the exchange master public key >
+
+The public key printed as the output of this command must be put into the configuration
+of the online machine:
+
+.. code-block:: ini
+ :caption: /etc/taler/conf.d/exchange-business.conf
+
+ [exchange]
+ MASTER_PUBLIC_KEY = YE6Q6TR1ED...
+
+ # ... rest of file ...
+
+The exchange HTTP service must be running before you can complete the offline
+signing procedure. Note that the exchange may be running without offline keys,
+but will not yet be operational. To make the exchange HTTP service
+operational, the following steps involving the offline signing machine must be
+completed:
+
+1. The public keys of various online keys used by the exchange service are exported
+ via a management HTTP API.
+2. The offline signing system validates this request and signs it.
+ Additionally, the offline signing system signs policy messages
+ to configure the exchange's bank accounts and associated fees.
+3. The messages generated by the offline signing system are uploaded
+ via the management API of the exchange HTTP service.
+
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# taler-exchange-offline \
+ download > sig-request.json
+
+ [root@exchange-offline]# taler-exchange-offline \
+ sign < sig-request.json > sig-response.json
+ [root@exchange-offline]# taler-exchange-offline \
+ enable-account payto://iban/$IBAN?receiver-name=$NAME > acct-response.json
+ [root@exchange-offline]# taler-exchange-offline \
+ wire-fee now iban EUR:0 EUR:0 EUR:0 > fee-response.json
+ [root@exchange-offline]# taler-exchange-offline \
+ global-fee now EUR:0 EUR:0 EUR:0 EUR:0 4w 4w 6y 4 > global-response.json
+ [root@exchange-online]# taler-exchange-offline upload < sig-response.json
+ [root@exchange-online]# taler-exchange-offline upload < acct-response.json
+ [root@exchange-online]# taler-exchange-offline upload < fee-response.json
+ [root@exchange-online]# taler-exchange-offline upload < global-response.json
+
+
+
+
+Setup Linting
=============
-This chapter provides an overview of the exchange configuration. Or at
-least eventually will do so, for now it is a somewhat wild description
-of some of the options.
+The ``taler-wallet-cli`` package comes with an experimental tool that runs various
+checks on the current GNU Taler exchange deployment:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# apt install taler-wallet-cli
+ [root@exchange-online]# taler-wallet-cli deployment lint-exchange
+
+You can optionally pass the ``--debug`` option to get more verbose output, and
+``--continue`` to continue with further checks even though a previous one has
+failed.
+
+
+Testing and Troubleshooting
+===========================
+
+The following shell session illustrates how the wallet can be used to withdraw
+electronic cash from the exchange and subsequently spend it. For these steps,
+a merchant backend is not required, as the wallet acts as a merchant.
+
+
+.. code-block:: shell-session
+
+ # This will now output a payto URI that money needs to be sent to in order to allow withdrawal
+ # of taler coins.
+ $ taler-wallet-cli advanced withdraw-manually --exchange $EXCHANGE_URL --amount EUR:10.50
+
+
+Show the status of the manual withdrawal operation.
+
+.. code-block:: shell-session
+
+ $ taler-wallet-cli transactions
+
+At this point, a bank transfer to the exchange's bank account
+needs to be made with the correct subject / remittance information
+as instructed by the wallet after the first step. With the
+above configuration, it should take about 5 minutes after the
+wire transfer for the incoming transfer to be observed by the
+Nexus.
+
+Run the following command to check whether the exchange received
+an incoming bank transfer:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# taler-exchange-wire-gateway-client \
+ --section exchange-accountcredentials-1 --credit-history
+
+Once the transfer has been made, try completing the withdrawal
+using:
+
+.. code-block:: shell-session
+
+ $ taler-wallet-cli run-pending
+
+Afterwards, check the status of transactions and show the
+current wallet balance:
+
+.. code-block:: shell-session
+
+ $ taler-wallet-cli transactions
+ $ taler-wallet-cli balance
+
+
+Now, we can directly deposit coins via the exchange into a target
+account. (Usually, a payment is made via a merchant. The wallet
+provides this functionality for testing.)
+
+.. code-block:: shell-session
+
+ $ taler-wallet-cli deposit create EUR:5 \
+ payto://iban/$IBAN?receiver-name=Name
+ $ taler-wallet-cli run-pending
+
+
+Check if this transaction was successful (from the perspective
+of the wallet):
+
+.. code-block:: shell-session
+
+ $ taler-wallet-cli transactions
+
+If the transaction failed, fix any open issue(s) with the exchange and
+run the "run-pending" command.
+
+The wallet can also track if the exchange wired the money to the merchant
+account. The "deposit group id" can be found in the output of the
+transactions list.
+
+.. code-block:: shell-session
+
+ $ taler-wallet-cli deposit track $DEPOSIT_GROUP_ID
+
+You can also check using the exchange-tools whether the exchange sent
+the an outgoing transfer:
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# taler-exchange-wire-gateway-client \
+ --section exchange-accountcredentials-1 --debit-history
+
+After enough time has passed, the money should arrive at the specified IBAN.
+
+
+
+Configuration Details
+=====================
+
+This chapter provides details about the exchange configuration.
+
+The configuration for all Taler components uses a single configuration file
+as entry point: ``/etc/taler/taler.conf``.
+
+System defaults are automatically loaded from files in
+``/usr/share/taler/config.d``. These default files should never be modified.
+
+The default configuration ``taler.conf`` configuration file also includes all
+configuration files in ``/etc/taler/conf.d``. The settings from files in
+``conf.d`` are only relevant to particular components of Taler, while
+``taler.conf`` contains settings that affect all components.
+
+
+The directory ``/etc/taler/secrets`` contains configuration file snippets with
+values that should only be readable to certain users. They are included with the ``@inline-secret@``
+directive and should end with ``.secret.conf``.
+
+To view the entire configuration annotated with the source of each configuration option, you
+can use the ``taler-config`` helper:
+
+
+.. code-block:: shell-session
+
+ [root@exchange-online]# taler-config --diagnostics
+ < ... annotated, full configuration ... >
+
+.. warning::
+
+ While ``taler-config`` also supports rewriting configuration files, we strongly
+ recommend to edit configuration files manually, as ``taler-config`` does not
+ preserve comments and, by default, rewrites ``/etc/taler/taler.conf``.
.. include:: frags/configuration-format.rst
@@ -1081,3 +1972,19 @@ time (operating system and user space) and other details.
Naturally, additional instrumentation (including using features of the
PostgreSQL database itself) may help discover performance issues.
+
+
+FIXMEs
+======
+
+* We should have some summary with the inventory of services that should be
+ running. Systemd by default doesn't show this nicely. Maybe suggest running
+ "systemd list-dependencies taler-exchange.target"?
+* When multiple TWGs are configured, which one will be used by the taler-exchange-transfer? CG: ALL!
+
+ * FD: Sure, for incoming transactions. But how does taler-exchange-transfer decide which TWG to use for an outgoing transaction?
+
+* What happens when the TWG doesn't like one particular outgoing transaction?
+ How to recover from that as a sysadmin when it happens in practice?
+* This document duplicates some details, should be de-duplicated!
+