diff options
author | Christian Grothoff <grothoff@gnunet.org> | 2023-04-18 10:26:04 +0200 |
---|---|---|
committer | Christian Grothoff <grothoff@gnunet.org> | 2023-04-18 10:26:04 +0200 |
commit | ffb0b262c29feb49a4c1a0080c5a1a07ed676865 (patch) | |
tree | 0fe749fd6d737818eaa32d75ac51e0da445902d3 | |
parent | 832e1118aa86f9e51976fb339203ffd41adaebc0 (diff) | |
download | docs-ffb0b262c29feb49a4c1a0080c5a1a07ed676865.tar.gz docs-ffb0b262c29feb49a4c1a0080c5a1a07ed676865.tar.bz2 docs-ffb0b262c29feb49a4c1a0080c5a1a07ed676865.zip |
combine setup guide and exchange manual
-rw-r--r-- | index.rst | 1 | ||||
-rw-r--r-- | taler-exchange-manual.rst | 935 | ||||
-rw-r--r-- | taler-exchange-setup-guide.rst | 950 |
3 files changed, 921 insertions, 965 deletions
@@ -57,7 +57,6 @@ Documentation Overview core/index taler-exchange-manual - taler-exchange-setup-guide taler-merchant-manual taler-merchant-api-tutorial taler-merchant-pos-terminal 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! + diff --git a/taler-exchange-setup-guide.rst b/taler-exchange-setup-guide.rst deleted file mode 100644 index 21f953b9..00000000 --- a/taler-exchange-setup-guide.rst +++ /dev/null @@ -1,950 +0,0 @@ -.. - This file is part of GNU Taler. - - Copyright (C) 2021-2023 Taler Systems SA - - GNU 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 - Foundation; either version 2.1, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - - @author Florian Dold - -GNU Taler Exchange Setup Guide -############################## - -This setup guide walks a system administrator through all steps required to -install an exchange and check that it is functional. For more background, -please read the :doc:`Operator Manual <taler-exchange-manual>`. - - -System Requirements -=================== - -This guide assumes that you are running Ubuntu 20.04 (Focal Fossa). - -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 - - - -Installation -============ - -Please see the chapter on `exchange installation <ExchangeInstallation>`_ for -various ways to install a GNU Taler exchange. - -Note that it is possible to run the HTTPS reverse proxy or -the PostgreSQL database on yet another host, but in these instructions we will -assume that only two hosts are used. Note that in addition to the exchange -you will thus need to install an HTTPS reverse proxy and the database: - -.. code-block:: shell-session - - [root@exchange-online]# apt-get update - [root@exchange-online]# apt-get install -y nginx postgresql - - -Configuration Basics -==================== - -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``. - - -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-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. - - -Setup Linting -============= - -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. - -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 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. - - -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 ... - - -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 Procedure -========================= - -The exchange HTTP service should be running now, but is not yet completely -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 - - - - -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. - - -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? |