Manual:Installation manual

From draglet wiki
Jump to: navigation, search

Contents

Server setup

Please perform all steps given in this document in the given order. They are built upon each other.

System requirements

The server-side system components of draglet run on Java, PHP, Apache httpd and MySQL. Some smaller support scripts are given in bash syntax.
All of these components can run on a wide range of operating systems. We have tested the full functionality on Debian 8. The package lists and configuration instructions work for a Debian 8 system with all package using the Debian 8 standard release and folder layout. To run draglet on a different operating system some instructions will need adjustment.
draglet components run independent of each other. By installing the components on separate servers many different system deployments are possible. We are giving three examples that cover the most frequent usages.

Deployment suggestions

Single server setup

All components are deployed to the same system. This type of setup is recommended for test installations with little need for wallet security and system performance.
A single Debian 8 server with at least 32 GB of RAM and a 500 GB hard disk for standard setup with one crypto currency (e.g. Bitcoin) and for each additional crypto currency (e.g. Litecoin or Ethereum) will be needed plus 300 GB of hard disk.
InstallationManual1.jpg

Cluster setup

Setup with 3 clustered servers. This type of setup is recommended for production setups of exchanges with low traffic and high security requirements.
Component distribution:
Server 1 runs the components cxServer (see 2.4) and cxClient (see 2.8).
Server 2 runs the components cxAdmin (see 2.3) and cxEngine (see 2.7).
Server 3 runs the component cxWallet (see 2.6).

Server hardware: Debian 8 server for each of the three servers with 16 GB of RAM and a 500 GB hard disk for Server 1 (frontend) and Server 2 (backend). For Server 3 (Bitcoin blockchain) in production mode will be needed 48 GB of RAM and a 1000 GB hard disk for a setup with one crypto currency and for each additional crypto currency will be needed plus 300 GB. For a faster performance for each of the three servers we recommend SSD (Solid State Drive) hard disk with above capacity. Besides that every server has to have a static IP address and the ability to run IPsec for security purposes.
Database: Replace package percona-server-server with package percona-xtradb-cluster-56 for all three servers and setup a database cluster as described in https://www.percona.com/software/mysql-database/percona-xtradb-cluster.
InstallationManual2.jpg

Server Installation

Required additional package sources

Some of the required packages are not available in the standard Debian repositories. We require some additional package sources.

Percona MySQL server

Execute these commands:

wget https://repo.percona.com/apt/percona-release_0.1-6.$(lsb_release -sc)_all.deb
dpkg -i percona-release_0.1-6.$(lsb_release -sc)_all.deb
rm percona-release_0.1-6.$(lsb_release -sc)_all.deb

Java 8

Create /etc/apt/sources.list.d/java8.list with this content:

deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main
deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main

Also add the key of the java server:

apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886

Configure locales

To ajust the server environment to your local settings eexecute the following command:

dpkg-reconfigure locales

and choose a locale configuration appropriate for your environment. When in doubt, choose "All locales" on the first screen and "en_US.UTF-8" as default locale on the second.

Perform initial update

Execute these commands:

apt-get update
apt-get upgrade

Package list

The following Debian 8 packages are required to run draglet:

apt-get install curl php5-dev php-pear pkg-config nmap ntp libzmq3 libzmq3-dev apache2 percona-server-server-5.6 php5-cli php5-mysql php5-curl php5-intl daemontools-run oracle-java8-installer ruby-compass libtool-bin maven ca-certificates lsb-release

Some packages are installed by default on Debian 8 which are not required to run draglet. Remove these:

apt-get remove rpcbind libnfsidmap2:amd64 nfs-common libtirpc1

Install ZMQ bindings for PHP

ZMQ bindings for PHP are required to run draglet. Execute these commands to install. When asked for prefix of libzmq installation, press <ENTER>:

pecl install zmq-beta
echo extension=zmq.so > /etc/php5/mods-available/zmq.ini
cd /etc/php5/cli/conf.d/
ln -s ../../mods-available/zmq.ini 20-zmq.ini
cd /etc/php5/apache2/conf.d/
ln -s ../../mods-available/zmq.ini 20-zmq.ini

Install ZMQ bindings for Java

ZMQ bindings for Java are required to run draglet. Execute these commands to install:

cd /root
wget https://github.com/zeromq/jzmq/archive/v3.1.0.tar.gz -O jzmq-3.1.0.tar.gz
tar zxf jzmq-3.1.0.tar.gz
cd jzmq-3.1.0
./autogen.sh
./configure --prefix=/opt/jzmq-3.1.0
nice make
make install

Install Composer

composer is required as dependency manager for all PHP-based components and is typically placed into /usr/local/bin.

cd /usr/local/bin/
curl -sS https://getcomposer.org/installer | php -- --filename=composer

Configure timezone for PHP

Local timezone needs to be configured for both PHP Apache module and PHP CLI.
You timezone identifier is a string like "Europe/Berlin". If you don't know the identifier of your local timezone, look it up here: timezoneconverter.com

In these two files:

  • /etc/php5/apache2/php.ini
  • /etc/php5/cli/php.ini

Find the line:

;date.timezone =

and change it to your local time zone. Here an example for Germany:

; Insert your timezone here
date.timezone = Europe/Berlin

Activate Apache modules. Execute these commands:

cd /etc/apache2/mods-enabled/
ln -s ../mods-available/rewrite.load .
ln -s ../mods-available/headers.load .
ln -s ../mods-available/expires.load .
ln -s ../mods-available/ssl.load .
ln -s ../mods-available/ssl.conf .
ln -s ../mods-available/php5* .
ln -s ../mods-available/socache_shmcb.load .
/etc/init.d/apache2 restart

Install Source Guardian for PHP

Execute these commands:

cd /root
wget http://www.sourceguardian.com/loaders/download/loaders.linux-x86_64.tar.gz
tar xzf loaders.linux-x86_64.tar.gz
cp ixed.5.6.lin /usr/lib/php5/20131226/
echo "extension=ixed.5.6.lin" > /etc/php5/mods-available/sg.ini
ln -s /etc/php5/mods-available/sg.ini /etc/php5/cli/conf.d/sg.ini
ln -s /etc/php5/mods-available/sg.ini /etc/php5/apache2/conf.d/sg.ini

Configure MTA

Exim4 is installed by default on Debian installations, but not configured. Execute this command:

dpkg-reconfigure exim4-config

Make sure to create a working configuration. Send a test e-mail to yourself to make sure that the configuration works:

mail me@example.org
Subject: email test

test test
.
Cc: 

Check /var/log/exim4/mainlog to see the results of your test.


Optional steps

The following steps go beyond the scope of this manual and should be executed by an experienced Linux system administrator. Your exchange installation will work without these steps, but lack some security features.

  • database cluster setup
  • database cluster security
  • system backup
  • VPN setup
  • encryption of wallet partitions

Components setup

Prepare database

Run the following commands from the linux shell to initially setup and configure the mysql database. When prompted for the password, insert the password you gave to the mysql administrative user in Chapter 1.3.5. Create the database “draglet” with specific character set:

mysql -u root -p -e 'CREATE DATABASE draglet DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;'

Setup the database users and save the passwords to your secured store:

mysql -u root -p -e 'CREATE user "api_frontend"@"localhost" identified by "<api_frontend password>";'
mysql -u root -p -e 'CREATE user "api_backend"@"localhost" identified by "<api_backend password>";'
mysql -u root -p -e 'CREATE user "api_btcd"@"localhost" identified by "<api_btcd password>";'

Prepare components

Create the cx-components folder, then download the release tar and copy it to /home/cx-components. Replace <version> with the latest version number from the draglet website throughout this manual. Run:

mkdir /home/cx-components
cd /home/cx-components
wget https://s3.eu-central-1.amazonaws.com/draglet-release/release-<version>/draglet-<version>.tar.bz2
tar xf draglet-<version>.tar.bz2

Create the folder /home/license.

mkdir /home/license

Order a draglet license from certificates@draglet.com and copy it to /home/license. The request for the license has to include the following:
Valid until, languages, currencies, DSO markets, market maker markets, number of ETH tokens, webshop merchants yes/no, URL, install ident.

Install cxAdmin

Unpack cxAdmin

cd /home/cx-components
tar jxf cx-admin-<version>.tar.bz2
ln -s /home/cx-components/cx-admin-<version> /home/cx-components/cx-admin

Set component parameters

Execute:

cp /home/cx-components/cx-admin/app/config/parameters.yml.dist /home/cx-components/cx-admin/app/config/parameters.yml

and then edit /home/cx-components/cx-admin/app/config/parameters.yml to match your environment and set the correct path to the license file.

Configuring AWS credentials

Amazon Web Services (AWS) is used for storing KYC related customer documents. It is configured through the aws_* parameters in /home/cx-components/cx-admin/app/config/parameters.yml.

If you do not wish to configure AWS at this point, make sure to set some dummy values into your parameters like this:

    aws_region: eu-west-1
    aws_access: xxx
    aws_secret: yyy
    aws_bucket: zzz

Bootstrap database

Change user to root to allow migrations to run. In /home/cx-components/cx-admin/app/config/parameters.yml set acces to the root user and password you have configured in 1.3.3:

database_user: root
database_password: <root password>

Setup database through migrations:

/home/cx-components/cx-admin/app/console doctrine:migrations:migrate

Reset database user privileges:

app/console draglet:setup:insert-permissions

In /home/cx-components/cx-admin/app/config/parameters.yml reset to the credentials you have created in 2.1:

database_user: api_backend
database_password: <api_backend password>

Finalize web-setup

Install assets, make cache and logs writable for the Apache process:

/home/cx-components/cx-admin/app/console assetic:dump
chmod 777 /home/cx-components/cx-admin/app/logs/ /home/cx-components/cx-admin/app/cache/

Setup Apache VHost

Create the Apache VHost file for cxAdmin.
The following occurrences of <vhost-name> should be replaced with cxClient's vhost with additional "admin”. Example: new-exchange.draglet.com -> admin.new-exchange.draglet.com
Create the file /etc/apache2/sites-available/<vhost-name>.conf.

<VirtualHost *:80>
  DocumentRoot /home/cx-components/cx-admin/web
  ServerName <vhost-name>
  # for production environment set prod
  # for test environment set test
  # for develop environment set dev
  SetEnv CX_ENV test

  <Directory /home/cx-components/cx-admin/web>
    Options FollowSymLinks
    AllowOverride All
    Require all granted
    # apache 2.2:
#    Order allow,deny
#    allow from all
  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/<vhost-name>-error.log
  LogLevel warn
  CustomLog ${APACHE_LOG_DIR}/<vhost-name>-access.log combined
</VirtualHost>

Activate the new VHost and restart Apache:

cd /etc/apache2/sites-enabled/
ln -s ../sites-available/<vhost-name>.conf .
/etc/init.d/apache2 restart

Create initial admin account(s)

Make up account credentials to access cx-Admin [user]/[password].
To create an admin user (put real_name into double quotes if necessary):

/home/cx-components/cx-admin/app/console draglet:admin:create-user [user] [real_name] [password]

Repeat step if necessary. To change the password of an existing admin user:

/home/cx-components/cx-admin/app/console draglet:admin:change-password [user] [password]

Manual configuration steps

If you insert currencies, which are not licensed, to the database, markets involving this currencies will not work and orders will not get executed. Please execute these commands to show the content of your license. Change entries of table setting to reflect the new setup by replacing "my-exchange" with the name of the new exchange. The installIdent will be visible in the chart names.
IMPORTANT: The value for "installIdent" must exactly match the value in your license file. The value for "baseUrl" must match the regular expression which is also mentioned in the license file. The system will not work if values do not match (the frontend will show error LICENSE_INVALID).

There are some examples, how to modify the settings table, as follows.

UPDATE setting SET value='support@<your-exchange>' WHERE id='mailToSupport';
UPDATE setting SET value='admin@<your-exchange>' WHERE id='mailToTech';
UPDATE setting SET value='admin@<your-exchange>' WHERE id='mailToVaultmaster';
UPDATE setting SET value='noreply@<your-exchange>' WHERE id='mailFromEmail';
UPDATE setting SET value='<your-exchange-indent>' WHERE id='installIdent';
UPDATE setting SET value='<your-exchange-base-url>' WHERE id='baseUrl';
UPDATE setting SET value='<your-name>' WHERE id='mailFromName';

Update e-mail templates in the settings table with new exchange name and remove the bootcamp texts.

To insert a currency, execute these sql statements.

Setup draglet services - charts-update, frontend-broker, mailer, orderbook

Create a file with the following content in /lib/systemd/system/cx-charts-update.service

[Unit]
Description=Draglet Charts Updater Service Unit
 
[Service]
Type=simple
ExecStart=/home/cx-components/cx-admin/app/console draglet:service:charts-updater --no-debug -e prod
User=www-data
Group=www-data
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Create a file with the following content in /lib/systemd/system/cx-frontend-broker.service

[Unit]
Description=Draglet Frontend Broker Service Unit
 
[Service]
Type=simple
ExecStart=/home/cx-components/cx-admin/app/console draglet:service:broker --no-debug -e prod
User=www-data
Group=www-data
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Create a file with the following content in /lib/systemd/system/cx-mailer.service

[Unit]
Description=Draglet Mailer Service Unit
 
[Service]
Type=simple
ExecStart=/home/cx-components/cx-admin/app/console draglet:service:mailer --no-debug -e prod
User=www-data
Group=www-data
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Create a file with the following content in /lib/systemd/system/cx-orderbook.service

[Unit]
Description=Draglet Orderbook Service Unit
 
[Service]
Type=simple
ExecStart=/home/cx-components/cx-admin/app/console draglet:service:orderbook --no-debug -e prod
User=www-data
Group=www-data
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Now create a softlink for each one of these files in /etc/systemd/system:

cd /etc/systemd/system
ln -s /lib/systemd/system/cx* .

Install cxServer

Unpack cxServer

cd /home/cx-components
tar jxf cx-server-<version>.tar.bz2
ln -s /home/cx-components/cx-server-<version> /home/cx-components/cx-server

Set component parameters

execute:

cp /home/cx-components/cx-server/app/config/parameters.yml.dist /home/cx-components/cx-server/app/config/parameters.yml

and then edit /home/cx-components/cx-server/app/config/parameters.yml to match your environment and set the correct path to the license file.

Finalize web-setup

Make cache and logs writable for the Apache process

rm -r /home/cx-components/cx-server/app/logs/* /home/cx-components/cx-server/app/cache/*
touch /home/cx-components/cx-server/app/logs/prod.log
touch /home/cx-components/cx-server/app/logs/dev.log (if needed)
touch /home/cx-components/cx-server/app/logs/test.log (if needed)
chmod -R  777 /home/cx-components/cx-server/app/cache/ /home/cx-components/cx-server/app/logs/

Install crypto daemons

IMPORTANT: Make sure to use the latest stable version and modify these commands accordingly.
It is not required to setup a crypto daemon for running the exchange. So only setup daemons you really need.
For each crypto daemon, setup one service in systemd. For the latest versions go to the corresponding download page: https://bitcoin.org/en/download
This should apply to all crypto-currencies. More can be downloaded from:
https://litecoin.org/
http://dogecoin.com/ (Dogecoin Core 64bit)
These additional crypto daemons are optional.
For the best functionality see the following chart:

(versions chart coming soon)

Add a user for running the crypto daemons and give him access to /home/secret/:

adduser cryptodaemon
mkdir -p /home/secret
chgrp cryptodaemon /home/secret

The details of the new user can be empty.

Additional packages required when compiling additional crypto daemons: NOTE: These are required only, when compiling from source.

apt-get install build-essential libssl-dev libdb-dev libdb++-dev libboost-all-dev libqrencode-dev

Install bitcoin daemon

Download, extract and install daemon to local directory:

cd /home/cryptodaemon
mkdir /home/cryptodaemon/.bitcoin
wget https://bitcoin.org/bin/bitcoin-core-0.*.*/bitcoin-0.*.*-linux64.tar.gz
tar zxf bitcoin-0.*.*-linux64.tar.gz
ln -s /home/cryptodaemon/bitcoin-0.*.*/bin/bitcoind /home/cryptodaemon/bin/bitcoind
*-please insert the desired version

Configure bitcoin daemon:
Generate a random password with at least 32 characters
Create /home/cryptodaemon/.bitcoin/bitcoin.conf as follows

checkblocks=6
checklevel=3
mempoolexpiry=1
rpcthreads=2
rpcuser=bitcoinrpc
rpcpassword=<32-char-random-string-generated-above>
deprecatedrpc=signrawtransaction

Give ownership to config .bitcoin directory to cryptodaemon-user:

chown -R cryptodaemon:cryptodaemon /home/cryptodaemon/.bitcoin

Create bitcoin service (/lib/systemd/system/cx-btcd.service):

[Unit]
Description=Bitcoin Service Unit
 
[Service]
Type=simple
WorkingDirectory=/home/cryptodaemon/
ExecStart=/home/cryptodaemon/bin/bitcoind -datadir=/home/cryptodaemon/.bitcoin/
User=cryptodaemon
Group=cryptodaemon
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

create a softlink for this service:

ln -s /lib/systemd/system/cx-btcd.service /etc/systemd/system/cx-btcd.service
  • Keep noted please that you should use `-deprecatedrpc=signrawtransaction` flag for each 4.0.5 cx-wallet setup only if you're using BTC version 0.17. If we're running 0.16.3 or other lower version this is not necessary.

Like:

`ExecStart= /home/cryptodaemon/bin/bitcoind -daemon -datadir=/home/cryptodaemon/.bitcoin/ -deprecatedrpc=signrawtransaction`

We will get rid of it in next 4.0.6 release.

Install ethereum daemon

To install the ethereum daemon download geth from https://geth.ethereum.org/downloads/.
Unpack the downloaded file by:

tar -zxvf <filename>.tar.gz

The geth binary will be located in the target folder.
Generate main address - start geth in console mode

/home/cryptodaemon/bin/geth --datadir=/home/cryptodaemon/.ethereum console
- type
"personal.newAccount();"
into the geth console, apply the password to parameters.yml and geth will answer with a fresh mainAddress

3. To start geth
- initially use

/home/cryptodaemon/bin/geth --verbosity 3 --datadir=/home/cryptodaemon/.ethereum --fast --rpc --rpcapi personal,eth,web3 --rpcaddr localhost --rpcport 8545 --cache 16 --trie-cache-gens 1

- while geth is syncing use

/home/cryptodaemon/bin/geth --datadir=/home/cryptodaemon/.ethereum attach
- to attach a new geth instance to the running one using ipc. You can access the geth console. Then type
"eth.syncing"
and check the sync status. When fully synced start geth like
/home/cryptodaemon/bin/geth --verbosity 3 --datadir=/home/cryptodaemon/.ethereum --rpc --rpcapi personal,eth,web3 --rpcaddr localhost --rpcport 8545 --cache 16 --trie-cache-gens 1

4. If fast sync is enabled and there is already a blokchain in the datadir (geth got restarted while syncing), geth will say "blockchain not empty, fast sync disabled". This asserts that fast syncing is only enabled on initial sync.

Create a systemd-file /lib/systemd/system/cx-geth.service:

[Unit]
Description=geth Service Unit
 
[Service]
Type=simple
WorkingDirectory=/home/cryptodaemon/
ExecStart=/home/cryptodaemon/bin/geth --datadir=/home/cryptodaemon/.ethereum --rpc --rpcapi personal,eth,web3 --rpcaddr localhost --rpcport 8545
User=cryptodaemon
Group=cryptodaemon
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

create a softlink for this service:

ln -s /lib/systemd/system/cx-btcd.service /etc/systemd/system/cx-geth.service

Install cxWallet

Unpack cxWallet

cd /home/cx-components
tar jxf cx-wallet-<version>.tar.bz2
ln -s /home/cx-components/cx-wallet-<version> /home/cx-components/cx-wallet

Set component parameters

execute:

cp /home/cx-components/cx-wallet/app/config/parameters.yml.dist /home/cx-components/cx-wallet/app/config/parameters.yml

and then edit /home/cx-components/cx-wallet/app/config/parameters.yml to match your environment.

database_driver:   pdo_mysql
database_host:     <host where your mysql is located>
database_port:     <port on which your mysql listens>
database_name:     draglet
database_user:     api_btcd
database_password: <password of your api_btcd database user>
license_file_path:  <path to your license file eg. /home/license/license.pem>
certificate_dir:    <path to your certs folder eg. /home/secret/certs>
install_ident:      <install ident from your license file>
backup_wallets:     <true|false depending if you want to backup your wallet keys>

#The wallet backup gets uploaded to amazon web services (encrpyted). So if you set backup true, you have top specify amazon data:

aws_region:         <amezon region eg. eu-west-1>
aws_access:         <amazon access>
aws_secret:         <amazon secret>

address_cache: <how much free addresses should the wallet generate eg. 10>

#If your cx-admin runs on a different host, you have to specify this host as broker host:

broker_host: localhost
broker_port: 38901

#If your cx-engine runs on a different host, you have to specify this host as balser host:

balser_host: localhost
balser_port: 38908

Also edit key "wallets" in /home/cx-components/cx-wallet/app/config/parameters.yml with the connection details created above, as in the following example. If you want to configure ethereum or ethereum tokens, create a main address first:

su - cryptodaemon
geth attach
personal.newAccount()

The address you receive from newAccount will serve as main address for the following configuration:

    wallets:
        BTC:
            port: 8332
            username: bitcoinrpc
            password: <rpcpassword from /home/cryptodaemon/.bitcoin/bitcoin.conf>
            passphrase: <SomePassphrase-BTC>
        LTC:
            port: 9332
            username: litecoinrpc
            password: <rpcpassword from /home/cryptodaemon/.litecoin/litecoin.conf>
            passphrase: <SomePassphrase-LTC>
        ETH:
            hostname: localhost
            port: 8545
            mainAddress: '<main address in single quote marks>'
            driver: Ethereum
            accountsPassword: <32 characters generated string>
            keystorePath: <path to datadir/keystore>

#All ethereum tokens will be served from this configuration.
#There is no need to configure each ethereum token separately.

        ETH_TOKEN:
            hostname: localhost
            port: 8545
            mainAddress: '<main address in single quote marks>'
            driver: EthereumToken
            accountsPassword: <32 characters generated string>
            keystorePath: <path to datadir/keystore>
    colorcore: 
        port: 6036
        username: bitcoinrpc
        password: null
        colorport: 6060
    mining_to: null
    trusted_users: {  }
    address_cache: 10
    require_balser: true
    secret_disguise: <SomePass-secret> ###### the same password for every draglet component (check the other parameters.yml files) ######
    wallets_confusion: false


IMPORTANT:
Currency codes ("BTC" and "LTC" in this example) have to match the database column currency.id.
Assert that ETH and ETH_TOKEN main address is wrapped in single quote marks.
You must not configure each ethereum token seperately. The ETH_TOKEN configuration gets applied to all ethereum tokens automatically.
You have to switch to the cryptodaemon user before creating a main address like mentioned above. Otherwise geth will not find your main address.
Make sure to always clear the cache (eg. rm -r /home/cx-components/cx-wallet/app/cache/*) if you changed the parameters.yml, otherwise the cx-wallet will not recognize your changes.

Funding the main address

If you have configured ethereum or ethereum tokens you have to fund your main address before you run your exchange system.
This means send a small amount of ether (eg. 10) to the main address directly.
This step is necessary because ethereum tokens get send to the main address on user deposits. This process needs initial ether for gas purposes.
Make sure that the fee you charging to your users is high enough to cover this gas cost.

Test daemon connection

Test bitcoin-based daemon connection setup by using:

/home/cx-components/cx-wallet/app/console draglet:talk-crypto <currency-code>

In the interactive shell, use "getblockcount" or "getinfo" and verify the daemon answers.
Note: Some daemons will not answer to RPC requests, before the block chain is completely synced.

Test ethereum-based daemon and ethereum token connection setup by using:

/home/cx-components/cx-wallet/app/console draglet:talk-geth <currency-code>

In case of connection problems (CommunicatorException):

  • make sure the daemon process is actually running (i.e. the daemontools service is starting it)
  • make sure connection details are correct (eg. username and password on bitcoin-based daemons)
  • make sure the port number is correct for the daemon (every currency uses a different rpc port and testnet installations usually use a port different from mainnet)

Create key-pair for encrypted user actions

Create a directory and place public/private key-pair there.

mkdir -p /home/secret/certs/users
chmod 710 /home/secret/certs
chgrp www-data /home/secret/certs
cd /home/secret/certs/
openssl genrsa -out btcd.pri 4096
openssl rsa -in btcd.pri -pubout -out ua-pubkey.pem

  • ua-pubkey.pem is the public key. It is required for cxServer.
  • btcd.pri is the private key. It is required for cxWallet.

IMPORTANT: Copy ua-pubkey.pem to /home/secret/certs/ua-pubkey.pem to any server running cxServer.

Add cxWallet service

Create the file /lib/systemd/system/cx-wallet.service

[Unit]
Description=Draglet Wallet Service Unit
After=mysql.service
RequiresMountsFor=/home/secret
 
[Service]
Type=simple
ExecStart=/home/cx-components/cx-wallet/app/console draglet:service:crypto-communicator --no-debug -e prod
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
User=root
Group=root
Restart=on-failure
RestartSec=10
StartLimitBurst=5
 
[Install]
WantedBy=multi-user.target

Don't forget to create the symlink to /etc/systemd/system

ln -s /lib/systemd/system/cx-wallet.service /etc/systemd/system/cx-wallet.service
After a
systemctl daemon-reload
you can
systemctl enable cx-wallet.service
the service and start it.

Install cxEngine

Unpack cxEngine

cd /home/cx-components 
tar jxf cx-engine-<version>.tar.bz2
ln -s /home/cx-components/cx-engine-<version> /home/engine

Configure engine

Create /home/engine/draglet.yml with the following content. Then replace and edit the values of the content with your details.

service_classes:
    - com.draglet.batch.EngineMarketAdmin
    - com.draglet.batch.RemoteExecutorMarketAdmin
    - com.draglet.batch.MapuAdmin
    - com.draglet.batch.BalserAdmin
    - com.draglet.batch.ShabaAdmin
    - com.draglet.batch.MebaAdmin
user: api_backend
passwd: <api_backend_password>
connection_url: "jdbc:mysql://<IP of your mysql server>:3306/draglet?serverTimezone=<your timezone>"
driver_class: "com.mysql.jdbc.Driver"
market_poll_interval: "5000"
matcher_sleep_time: "100"
fetcher_sleep_time: "3000"
engine_remex_socket_connection: "tcp://127.0.0.1:5517"
engine_publisher_socket_connection: "tcp://127.0.0.1:38905"
engine_server_socket_connection_base: "tcp://0.0.0.0:38920"
remex_publisher_socket_connection: "tcp://127.0.0.1:38907"
orderbook_service_socket_connection: "tcp://127.0.0.1:38909"
broker_socket_connection: "tcp://127.0.0.1:38903"
remex_inproc_socket_connection: "tcp://127.0.0.1:38910"
last_quote_writer_timeout: "60000"
engine_inproc_socket_connection: "inproc://engine"
fetcher_inproc_socket_connection: "inproc://fetcher"
ioc_inproc_socket_connection: "inproc://ioc"
dso_client_certs_path: "/home/certs/client-certs/"
ignore_http_host: "true"
maker_order_synchronizer_sleep_time: "600000"
connection_pool_size: "60"
merchant_inproc_socket_connection: "inproc://merchant"
merchant_publisher_socket_connection: "tcp://127.0.0.1:38911"
shaba_inproc_socket_connection: "tcp://127.0.0.1:38919"
shaba_publisher_socket_connection: "tcp://127.0.0.1:38913"
# TEST: confidence_check_url: "https://chain.so/api/v2/get_confidence/BTCTEST/"
confidence_check_url: "https://chain.so/api/v2/get_confidence/BTC/"
balser_valid_period: "300"
balser_server_socket_connection: "tcp://0.0.0.0:38908"
balser_client_socket_connection: "tcp://127.0.01:38908"
executor_client_count: "3"
remex_worker_count: "5"
engine_balser_inproc_socket_connection: "inproc://engine_balser"
engine_balser_timeout: "3000"
license_file_path: /home/license/license.pem
icinga_base_path: /tmp/ic-engine
 
# for an itBit connected installation add also:
# itbit_base_path: "https://beta-api.itbit.com/v1"
# itbit_orderbook_path: "https://beta.itbit.com/api/feeds/orderbook/%s"
# itbit_client_key: "<obtain from customer>"
# itbit_api_secret: "<obtain from customer>"
# itbit_user_id: "<obtain from customer>"
# itbit_wallet_id: "<obtain from customer>"
 
# for a bitstamp cnnected installation add:
# bitstamp_client_key: "<obtain from customer>"
# bitstamp_api_secret: "<obtain from customer>"
# bitstamp_user_id: "<obtain from customer>"

Create cx-engine services

Create the file /lib/systemd/system/cx-charts-update.service

[Unit]
Description=Draglet Charts Updater Service Unit
 
[Service]
Type=simple
ExecStart=/home/cx-components/cx-admin/app/console draglet:service:charts-updater --no-debug -e prod
User=www-data
Group=www-data
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Create the file /lib/systemd/system/cx-frontend-broker.service

[Unit]
Description=Draglet Frontend Broker Service Unit
 
[Service]
Type=simple
ExecStart=/home/cx-components/cx-admin/app/console draglet:service:broker --no-debug -e prod
User=www-data
Group=www-data
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Create the file /lib/systemd/system/cx-mailer.service

[Unit]
Description=Draglet Mailer Service Unit
 
[Service]
Type=simple
ExecStart=/home/cx-components/cx-admin/app/console draglet:service:mailer --no-debug -e prod
User=www-data
Group=www-data
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Create the file /lib/systemd/system/cx-orderbook.service

[Unit]
Description=Draglet Orderbook Service Unit
 
[Service]
Type=simple
ExecStart=/home/cx-components/cx-admin/app/console draglet:service:orderbook --no-debug -e prod
User=www-data
Group=www-data
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Create the file /lib/systemd/system/cx-engine.service

[Unit]
Description=Draglet Engine Service Unit
 
[Service]
Type=simple
ExecStart=/usr/bin/java -Xss256k -Xmx1024m -XX:+ExitOnOutOfMemoryError \
    -cp /opt/jzmq-3.1.0/share/java/zmq.jar:*:lib/* \
    -Dlog4j.configurationFile=log4j2.xml -DisThreadContextMapInheritable=true \
    com.draglet.batch.Batch draglet.yml
WorkingDirectory=/home/engine
Environment=LD_LIBRARY_PATH=/opt/jzmq-3.1.0/lib
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

Now create the symlinks for these files:

ln -s /lib/systemd/system/cx-charts-update.service /etc/systemd/system/cx-charts-update.service
ln -s /lib/systemd/system/cx-frontend-broker.service /etc/systemd/system/cx-frontend-broker.service
ln -s /lib/systemd/system/cx-mailer.service /etc/systemd/system/cx-mailer.service
ln -s /lib/systemd/system/cx-orderbook.service /etc/systemd/system/cx-orderbook.service
ln -s /lib/systemd/system/cx-engine.service /etc/systemd/system/cx-engine.service

Enable the services with

systemctl daemon-reload
systemctl enable cx-*

Change entries of the table setting to reflect the new setup by replacing the value of id=baseUrl and id=installIdent with the information from the license for the exchange which you are setting up (othervise some of the draglet service units will not work)

/home/cx-components/cx-admin/app/console  draglet:license
mysql --defaults-file=/etc/mysql/debian.cnf -e "update draglet.setting set value='https://exchange.example.com/' where id='baseUrl';";
mysql --defaults-file=/etc/mysql/debian.cnf -e "update draglet.setting set value='<installIdent>' where id='installIdent';";

Install cxClient

Unpack cxClient

cd /home/cx-components
tar jxf cx-client-<version>.tar.bz2
ln -s /home/cx-components/cx-client-<version> /home/web
cd /home/web
chgrp -R www-data * .htaccess

Setup Apache Vhost for your frontend of the exchange

Create the Apache VHost file for cxCLient.
The following occurrences of <vhost-name> should be replaced with cxClient's vhost. Example: new-exchange.draglet.com
Create the file /etc/apache2/sites-available/<vhost-name>.conf.

ExpiresActive On
ExpiresDefault "now"
<Directory /home/web/components/>
    ExpiresDefault "access plus 1 months"
</Directory>
<Directory /home/web/releases/>
    ExpiresDefault "access plus 1 months"
</Directory>
<VirtualHost *:80>
    ServerName <vhost-name>
    SetEnv API_PATH "/home/cx-components/cx-server/"
    SetEnv CX_ENV prod
    RewriteEngine On
    RewriteRule ^/?(.*)$ https://<vhost-name>/$1 [R=301,L]
</VirtualHost>
<VirtualHost *:443>
    ServerName <vhost-name>
    SetEnv API_PATH "/home/cx-components/cx-server/"
    # for production environment set prod
    # for test environment set test
    # for develop environment set dev
    SetEnv CX_ENV prod
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^<vhost-name>
    RewriteRule ^/?(.*)$ https://<vhost-name>/$1 [R=301,L]
 
    SetEnvIf User-Agent ".*MSIE [1-5].*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
    SetEnvIf User-Agent ".*MSIE [6-9].*" ssl-unclean-shutdown
     
    # HSTS (mod_headers is required) (15768000 seconds = 6 months)
    Header always add Strict-Transport-Security "max-age=15768000"
    DocumentRoot /home/web
 
    <Directory /home/web>
        Options FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
 
    SSLCertificateFile <location of your ssl_certificate_file>
    SSLCertificateKeyFile <location of the according ssl_certificate_key_file>
 
    ErrorLog ${APACHE_LOG_DIR}/<vhost-name>-error.log
    LogLevel warn
    CustomLog ${APACHE_LOG_DIR}/<vhost-name>-access.log combined
</VirtualHost>

Setup Apache Vhost for port 443 (ssl)

To enable a ssl connection a certificate file has to be generated.

cd /home/secret/certs
openssl genrsa -des3 -out server.key 2048
openssl req -new -key server.key -out server.csr

You can decide either to self sign the certificate or let it sign by a trust authority. If you sign it by yourself execute

cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Please be aware that a user will get a not-trusted-certificate message in the browser if he logs into the exchange when self signing. If you do not want to self sign the certificate, send the server.csr to a trust authority and get a server.crt in return.

Create the Apache VHost file for cxCLient.
The following occurrences of <vhost-name> should be replaced with cxClient's vhost. Example: new-exchange.draglet.com
Create the file /etc/apache2/sites-available/<vhost-name>.conf.

<VirtualHost *:443>

   ServerName <vhost-name>

   SetEnv API_PATH "/home/cx-components/cx-server/"
   # for production environment set prod
   # for test environment set test
   # for develop environment set dev
   SetEnv CX_ENV test

   SSLEngine on
   SSLCertificateFile /home/secret/certs/server.crt
   SSLCertificateKeyFile /home/secret/certs/server.key

   SSLProtocol             all -SSLv2 -SSLv3
   SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
   SSLHonorCipherOrder     on

   SetEnvIf User-Agent ".*MSIE [1-5].*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
   SetEnvIf User-Agent ".*MSIE [6-9].*" ssl-unclean-shutdown

   # HSTS (mod_headers is required) (15768000 seconds = 6 months)
   Header always add Strict-Transport-Security "max-age=15768000"

   DocumentRoot /home/web
   <Directory /home/web>
    Options FollowSymLinks
    AllowOverride All
    Require all granted
   </Directory>

   ErrorLog ${APACHE_LOG_DIR}/<vhost-name>-error.log
   LogLevel warn
   CustomLog ${APACHE_LOG_DIR}/<vhost-name>-access.log combined
</VirtualHost>

Activate VHost and restart Apache

cd /etc/apache2/sites-enabled/
ln -s ../sites-available/<vhost-name>.conf .
/etc/init.d/apache2 restart

Component update

The update process is the same as the installation process. After downloading and unpacking the draglet installation file compare the component versions to the downloaded versions. Only for the components that have changed rerun the installation process.

Initial setup

Setup account holders

Within a market setup, some system users for price differences and fees, the so called “Account holders”, have to be defined. This users get charged price or fee difference which may occur within remote executions at a liquidity provider. Furthermore the specified users get credited the fees which are paid by customers.
After a user was created using cxClient, the following sql commands might have to be executed to manual set the user enabled.

UPDATE user set enabled = 1 WHERE email ='<the users email address>';

Setup market makers

This step is optional and only needed if you want to set up automatic market makers. To set up a market maker the specific market has to be licensed. A market maker could be edited via cx-Admin by click on the target symbol at the actions area in market overview. To create a market maker, it has to be inserted into the database directly using following query.

INSERT INTO market_maker (market_id, maker_active, taker_active, base_price_definer, orders_per_side, min_volume_limit, offset_strategy) 
VALUES 
(<your_market_id>,
 <1=makers are active,
 0=markers are not active>,
<1=takers are active,
0=takers are not active>,
<'chart'=the current chart value will be used as base price,
'fixed'=a fixed price will be used as base price
>,
<number of orders that will be inserted at bid and ask side>,
<the minimum volume of an order, multiplied with 1e8>,
<'absolute'=the limit difference between two orders will be absolute,
'percentages'=the limit difference between two orders is percentage based
>);

To configure the market maker, the field “offset_strategy_config” as well as the field “base_price_definer_config” are used.
Therefore, json formated data has to be inserted into the corresponding fields, like in the following examples.

UPDATE market_maker SET offset_strategy_config= '
{"offset": <your offset like 0.15 for 0.15 %(percentaged) or 0.15 (absolute)>}
' WHERE market_id = <the corresponding market id>;

UPDATE market_maker SET base_price_definer_config= '
{"price": <your base price like 5 (fixed)>}
' WHERE market_id = <the corresponding market id>;

Please note that the field “base_price_definer_config” should only be filled if the base_price_definer “fixed” is chosen.
Futhermore, the market maker api path has to be configured. Therefore edit the file /home/cx-admin/app/config/parameters.yml and insert the value for the parameter “market_maker_api”. The parameter represents the protocol and the first part of the draglet api like the following example.

market_maker_api: 'http://<your-exchange>/gateway'

Within the next step the market maker/taker user email has to be configured in the setting table.
To achieve this, new system users have to be created. This user will be chosen if an order will be placed.
Create a system user for market maker:
maker@your-exchange.com
And a system user for market taker:
taker@your-exchange.com

UPDATE setting SET value='maker@your-exchange.com' WHERE id='marketMakerUser';

To activate the market taker, the taker user email has to be configured in the setting table as well.

UPDATE setting SET value='taker@your-exchange.com' WHERE id='marketTakerUser';

Do not insert values for maker/taker user password in the setting table as authentication is token based in most recent versions.
Assert that the secret for token based authentication is set in cxAdmin's and cxServer's parameters.yml file. Therefore create a secret with the following command:

pwgen 40 1

Place the secret as parameters.yml value:

secret_disguise: <output of pwgen 40 1>

Save the parameters.yml files and clear the caches with:

rm -r /home/cx-components/cx-server/app/cache/*
rm -r /home/cx-components/cx-admin/app/cache/*

To start the market makers create the file /etc/cron.d/maker with the following content (replace "-e test" with "-e prod" for production systems and ensure that the crontab has a blank line at the end):

# market maker
*/3     * * * * www-data    /usr/bin/env php /home/cx-components/cx-admin/app/console draglet:cron:market-maker -e test
*       * * * * www-data    /usr/bin/env php /home/cx-components/cx-admin/app/console draglet:cron:market-taker -e test


Exchange maintenance

Show license content

To show the content of your license execute the following commands.

cd /home/cx-components/cx-admin
app/console draglet:license:content

cxAdmin logs

cxAdmin logs are located in /home/cx-components/cx-admin/app/logs. For test installations (as configured in 2.3.5, 2.3.8, 2.3.9 and 2.3.10) the name of the log is test.log. For prod installations it is prod.log.

cxServer logs

cxServer logs are located in /home/cx-components/cx-server/app/logs. For test installations (as configured together with cxClient in 2.7.2) the name of the log is test.log. For prod installations it is prod.log.

cxWallet logs

cxWallet logs are located in /home/cx-components/cx-wallet/app/logs. For test installations (as configured in 2.5.10) the name of the log is test.log. For prod installations it is prod.log.

cxEngine logs

cxEngine logs are located in /home/engine/logs. Each engine module writes separate logs.

  • engine.log has orderbook information and (remote-)trade executions.
  • balser.log has account locking information.
  • shaba.log and mapu.log have DSO publishing and execution information.
  • fetcher.log provides polling information from non-draglet exchanges.
  • meba.log shows informations concerning merchant backend.

cxClient logs

The client logs to the Javascript console of the browser.

Operator mails

In case of system failures the component send e-mails to the address configured in 1.3.8.


Additional cxEngine configuration

To configure cxEngine, it is possible to add the following parameters to draglet.yml.

passwd: <password of your api_backend database user>
license_file_path: <path to your license file, e.g. /home/license/license.pem>
service_classes:
 - com.draglet.batch.BalserAdmin
 - com.draglet.batch.ShabaAdmin
 - com.draglet.batch.MapuAdmin
 - com.draglet.batch.EngineMarketAdmin
 - com.draglet.batch.RemoteExecutorMarketAdmin
 - com.draglet.batch.MerchantAdmin

Add currency

After executing one of the SQLs below wait for 10 min. until the chart updater process has created the chart categories.
If you insert currencies, which are not licensed, to the database, markets involving this currencies will not work and orders will not get executed. Please execute these commands to show the content of your license.

Fiat currency

Replace USD and US Dollar in this script with the currency you are creating:

INSERT INTO draglet.currency (id, name, type_id, deposit_text, minimum_withdrawal) VALUES ('USD', 'US Dollar', 1, 'Please change the deposit text in the back office application', 500000000);
INSERT INTO account (user_id, currency_id, balance) SELECT id, 'USD', 0 FROM user;

Crypto currency

Replace BTC and Bitcoin in this script with the currency you are creating, fees are changing fast and must be set to an appropriate value:

INSERT INTO draglet.currency (id, name, type_id, wanted_confirmations, standard_fee, tx_fee_per_kb, minimum_withdrawal, manual_conversion_input, sort_order, `leading`, num_decimals) VALUES ('BTC', 'Bitcoin', 2, 6, 100000, 200000, 500000, 0, 0, 0, 8);
INSERT INTO account (user_id, currency_id, balance) SELECT id, 'BTC', 0 FROM user;

ETH needs a different tx fee and draglet uses only 8 decimals places of the 18 places that are used in the Ethereum network:

INSERT INTO draglet.currency (id, name, type_id, wanted_confirmations, standard_fee, tx_fee_per_kb, minimum_withdrawal, manual_conversion_input, sort_order, `leading`, num_decimals) VALUES ('ETH', 'Ethereum', 2, 6, 1000000, 2100000000000, 10000000, 0, 0, 0, 8);
INSERT INTO account (user_id, currency_id, balance) SELECT id, 'ETH', 0 FROM user;

Add language

If you insert languages, which are not licensed, to the database, services involving this languages will not work. Please execute these commands to show the content of your license.
Replace pl and Polski in this script with the language you want to set up. The individual e-mail texts are edited in the cxAdmin interface:

INSERT INTO `language`(`id`, `name`, `active`) VALUES ('pl','Polski',1)
INSERT INTO `email` (`ident`, `language`, `mime_type`, `subject`, `content`) VALUES
('account_deleted', 'pl', 'text/plain', 'Account at <exchange>.com deleted', 'we have deleted your user account as requested.\n\nWe hope to see you again in the future.'),
('mail_change', 'pl', 'text/plain', 'New email address at <exchange>.com', 'You requested to change your email address. Please confirm your new email address by clicking the following link:\n{{ link }}\n\nIf you do not wish to change your current email address, please ignore this mail - the link provided is only valid for 24 hours.'),
('mail_changed', 'pl', 'text/plain', 'Email address changed', 'You have successfully confirmed your new email address.\n\nWe will only use this new email address for contacting you in the future.'),
('password_change', 'pl', 'text/plain', 'Password change at <exchange>.com', 'we received a request to reset your password.\n\nIf you want to reset your password, please click on the following link and set your new password:\n\n{{ link }}\n\nPlease note that the link only remains valid for one hour.\nIn case you do not want to reset your password, simply ignore this email - no actions will be taken.'),
('payment_canceled', 'pl', 'text/plain', 'payment canceled', 'A payment of {{amountBTC}} {{cryptoCurrencyCode}} ({{amountFiat}} {{fiatCurrencyCode}}) for the reference {{referenceId}} received at {{receivedTime}} was canceled.\nRisk option: {{riskOption}}.\nThe transaction id is {{transactionId}}. It has {{confirmations}} confirmations and requires {{wantedConfirmations}} confirmations.'),
('payment_confirmed', 'pl', 'text/plain', 'payment confirmed', 'A payment of {{amountBTC}} {{cryptoCurrencyCode}} ({{amountFiat}} {{fiatCurrencyCode}}) for the reference {{referenceId}} received at {{receivedTime}} was confirmed.\nRisk option: {{riskOption}}.\nThe transaction id is {{transactionId}}. It has {{confirmations}} confirmations and requires {{wantedConfirmations}} confirmations.'),
('payment_received', 'pl', 'text/plain', 'payment received', 'A payment of {{amountBTC}} {{cryptoCurrencyCode}} ({{amountFiat}} {{fiatCurrencyCode}}) for the reference {{referenceId}} was received at {{receivedTime}}.\nRisk option: {{riskOption}}.\nThe transaction id is {{transactionId}}. It has {{confirmations}} confirmations and requires {{wantedConfirmations}} confirmations.'),
('registration', 'pl', 'text/plain', 'Your registration at <exchange>.com', 'Thank you for your registration for <exchange>.\r\n\r\nIn order to complete your registration, please confirm your e-mail address through the following link:\r\n\r\n{{ link }}\r\n\r\nAfter activating the link, the registration process should be completed and your account is ready to use.\r\n\r\nIn case you did not try to register with your e-mail address, simply ignore this e-mail. If the registration process is incomplete, we will delete your data after a 24 hours.\r\n\r\n'),
('request_delete', 'pl', 'text/plain', 'Account deletion request at <exchange>.com', 'You have requested to delete your user account. Please click the following link to confirm the deletion:\n{{ link }}\n\nIf you do not want to delete your account, simply ignore this email. The link provided is only valid for one hour.'),
('two_factor', 'pl', 'text/plain', '2-Factor Code', 'we hereby send your requested 2-Factor authentication code.\n\nYour code is: {{ code }}\n\nIf you did not interact with our website in a way, that requires seperate authentication, please contact us immediately.'),
('welcome', 'pl', 'text/plain', 'Welcome to <exchange>.com', 'thank you very much for your registration to <exchange>.\r\n\r\n{{ link }}\r\n\r\nThe registration process has been completed, you are now enabled to log in to your account.\r\n\r\nWe hope you will enjoy a great and hopefully successful time with <exchange>!');
INSERT INTO `setting` (`id`, `modified_by_id`, `value`, `type`, `description`, `version`, `modified_at`, `editable`, `license_option`) VALUES
('mailLayout_pl_text-plain', 1, 'Dear customer,\r\n\r\n{% block content %}{% endblock %}\r\n\r\nBest regards,\r\nyour <exchange> team.\r\n\r\n--\r\ninfo@<exchange>.com', 'textarea', 'text/plain Layout for emails in polish', 4, '2014-12-03 10:11:09', 0, NULL);

In addition to these scripts you have to copy the files labels-locale_en.js and messages-locale_en.js in the i10n folder to files with your new language code. In this example they would be copied to labels-locale_pl.js and messages-locale_pl.js. Then edit the new files (labels-locale_pl.js and messages-locale_pl.js) to start with:

var labelsLocale_pl = {
var messagesLocale_pl = {

In the file /home/web/index.html find the lines:

<script src="@BRANCH@/l10n/labels-locale_en.js" type="text/javascript"></script>
<script src="@BRANCH@/l10n/messages-locale_en.js" type="text/javascript"></script>

and after these lines add two new lines:

<script src="@BRANCH@/l10n/labels-locale_pl.js" type="text/javascript"></script>
<script src="@BRANCH@/l10n/messages-locale_pl.js" type="text/javascript"></script>

In the two new files translate the labels and messages to the target language.
The last step is to copy /home/web/releases/master/content/en to /home/web/releases/master/content/pl and translate the content to the target language.

Upgrade installation

When upgrading a draglet system, minor versions numbers must match, i.e. cx-server-3.8.x is compatible with cx-admin-3.8.x and cx-engine-3.8.x, and so on.

Components should be upgraded in a certain order, that is, cx-admin first, then cx-client, then cx-server, then cx-engine and cx-wallet.

Starting the upgrade

Make sure all the updated packages are extracted to /home/cx-components/. In this example, we're upgrading from 3.7.6 to 3.8.0. Make sure to replace the version numbers where necessary.

Stop the services, the webserver and the cron daemon. While it is possible to upgrade while the system is running, draglet recommends to follow these procedures.

cd /etc/service
svc -d charts-generator engine frontend-broker mailer-service orderbook-service

/etc/init.d/apache2 stop

/etc/init.d/cron stop

Sometimes services take a few seconds to stop or fail to stop. Using the svstat and ps tools, make sure that the services processes are stopped. If you notice a process staying alive, use the kill tool with the -9 switch as a last resort, to stop the service.

Upgrade cx-admin

Switch cx-admin to new version

Change to the new version's directory afterwards:

cd /home/cx-components/
rm cx-admin
ln -s cx-admin-3.8.0 cx-admin
cd cx-admin

Set parameters

Apply the distribution parameters.yml file:

cp app/config/parameters.yml.dist app/config/parameters.yml

and apply the same adaptions to your parameters as in your original setup.

Alternatively, copy the parameters.yml file from you old version, compare the .dist files from your old version and your new version and add any missing parameters.

Configure root database access

Open app/config/parameters.yml in an editor. Find the database access credentials section:

    database_user: api_backend
    database_password: <password-for-api_backend>

and copy them to a temporary location. Replace these with full access credentials:

    database_user: root
    database_password: <password-for-root>

and save the file.

Run migrations

Before running the migrations update the properties in app/config/parameters.yml as follows.

aws_region: eu-west-1
aws_access: xxxxx
aws_secret: yyyyy
aws_bucket: dummy-bucket

Assert that your license file is located like configured in app/config/parameters.yml. The default license location is as follows.

/home/license/license.pem

Update the database schema by running:

app/console doctrine:migrations:migrate

Configure original database access

Open app/config/parameters.yml and re-configure the original access credentials:

    database_user: api_backend
    database_password: <password-for-api_backend>

Insert new privileges

Update the access privileges:

app/console draglet:setup:insert-permissions

Restart cx-admin services

Make sure that the logs and cache directories are writable and that no cache exists:

rm -r app/cache/*
chmod 777 app/cache/ app/logs/

Restart the cron daemon and the services of cx-admin:

/etc/init.d/cron start

cd /etc/service
svc -d charts-generator frontend-broker mailer-service orderbook-service

Upgrade cx-client

Switch cx-client to new version

Change to the new version's directory afterwards:

cd /home
rm web
ln -s /home/cx-components/cx-client-3.8.0 web

Changes you have applied to cx-client by changing the files contained within /home/web must be merged to the new client version manually. Please give the new client files contained in cx-client-3.8.0.tar.bz2 to your web developer and ask him to do the merge before installing the upgrade.

Upgrade cx-server

Switch cx-server to new version

Change to the new version's directory afterwards:

cd /home/cx-components/
rm cx-server
ln -s cx-server-3.8.0 cx-server
cd cx-server

Set parameters

Apply the distribution parameters.yml file:

cp app/config/parameters.yml.dist app/config/parameters.yml

and apply the same adaptions to your parameters as in your original setup.

Alternatively, copy the parameters.yml file from you old version, compare the .dist files from your old version and your new version and add any missing parameters.

Restart Apache

Make sure that the logs and cache directories are writable and that no cache exists:

rm -r app/cache/*
chmod 777 app/cache/ app/logs/
/etc/init.d/apache2 start

Upgrade cx-engine

Switch cx-engine to new version

Change to the new version's directory afterwards:

cd /home
rm engine
ln -s /home/cx-components/cx-engine-3.8.0 engine
cd engine
copy /home/cx-components/cx-engine-3.7.6/draglet.yml .

Upgrade cx-wallet

Switch cx-wallet to new version

Change to the new version's directory afterwards:

cd /home/cx-components/
rm cx-wallet
ln -s cx-wallet-3.8.0 cx-wallet
cd cx-wallet

Set parameters

Apply the distribution parameters.yml file:

cp app/config/parameters.yml.dist app/config/parameters.yml

and apply the same adaptions to your parameters as in your original setup.

Alternatively, copy the parameters.yml file from you old version, compare the .dist files from your old version and your new version and add any missing parameters.

Restart cx-wallet service

Make sure that the logs and cache directories are writable and that no cache exists:

rm -r app/cache/*
chmod 777 app/cache/ app/logs/
cd /etc/service
svc -u wallet-service

Connect a market to the DSO

Create subdomain

In order to run the DSO on your exchange you need a new subdomain dso.<yourexchange> that works with SSL because client authentication in the DSO is certificate based. Create a self signed SSL certificate for the dso vhost with openssl.
Therefore, firstly create the folder /home/certs/. This folder is dedicated for storing the certificates.

mkdir /home/certs

Then navigate to the folder and execute the following commands. Please fill in reasonable details when prompted for country, company, passwords etc by the wizard.
Please enter dso.<yourexchange> (e.g. dso.draglet.com) as common name when prompted.

cd /home/certs
openssl genrsa -des3 -out dso.key 2048
openssl req -new -key dso.key -out dso.csr
cp dso.key dso.key.org
openssl rsa -in dso.key.org -out dso.key
openssl x509 -req -days 365 -in dso.csr -signkey dso.key -out dso.crt

Request client certificate

From certificates@draglet.com request a client certificate for each dso connection, as well as the file dragletCA.crt that is referenced in the vhost file of the next chapter. The request must include the following information:

source market
target market
remote-name

The client certificate's remote-name is referred to as <new-client> in the scripts below. The remote-name is also mentioned within the exchange table (col. name). The remote name follows the pattern <your_exchange>_<target_currency>. If you want to connect your local EUR market to a dso EUR market the remote-name would be <dso_exchange_name>_eur.
You need a certificate for every DSO connection of your new market. If your market receives liquidity from trust deposit and connects to two other local markets you need 3 certificates for this market in order to identify it correctly via the DSO. In this example the two other local markets also need one certificate each as described in 5.5.
Create the folder /home/certs/client-certs. This folder is dedicated to store the mentioned client certificates.

mkdir /home/certs/client-certs

Create market

Create the new market as explained in Manual:Admin Interface. The database id of the new market is referred to as <market_id> in the scripts below.
Register a user to become the nostro account holder of your new market. The user id is referred to as <nostro_account_holder_id> in the scripts below. The nostro account will mirror your account balance on this DSO connection. The created user should be set to enabled like explained in chapter 3.1. Then set the user to trusted with this statement:

UPDATE user set trusted= 1 WHERE email ='<the users email address>';

Create vhost for subdomain

Create a vhost file named dso.<yourexchange>.conf (e.g. dso.draglet.com.conf) with the following content:

ExpiresActive On
ExpiresDefault "now"

<Directory /home/web/components/>
        ExpiresDefault "access plus 1 months"
</Directory>
<Directory /home/web/releases/>
        ExpiresDefault "access plus 1 months"
</Directory>

<VirtualHost *:443>

  ServerName dso.<yourexchange>

  SetEnv API_PATH "/home/cx-components/cx-server/"
 	    # for production environment set prod
  	  # for test environment set test
        # for develop environment set dev
  SetEnv CX_ENV prod

  SSLEngine on
  SSLCertificateFile /home/certs/dso.crt
  SSLCertificateKeyFile /home/certs/dso.key

    SSLCACertificateFile    /home/certs/client-certs/dragletCA.crt
    SSLVerifyClient         optional
    SSLVerifyDepth          1
    SSLOptions              +StdEnvVars

    SSLProtocol             all -SSLv2 -SSLv3
    SSLCipherSuite          ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
    SSLHonorCipherOrder     on

    SetEnvIf User-Agent ".*MSIE [1-5].*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
    SetEnvIf User-Agent ".*MSIE [6-9].*" ssl-unclean-shutdown

    # HSTS (mod_headers is required) (15768000 seconds = 6 months)
    Header always add Strict-Transport-Security "max-age=15768000"

  DocumentRoot /home/web
  <Directory /home/web>
    Options FollowSymLinks
    AllowOverride All
    Require all granted

  </Directory>

  ErrorLog ${APACHE_LOG_DIR}/dso.<yourexchange>-error.log
  LogLevel warn
  CustomLog ${APACHE_LOG_DIR}/dso.<yourexchange>-access.log combined
</VirtualHost>

If SSL isn't enabled in your apache config yet, do it now:

cd /etc/apache2/mods-enabled/
ln -s ../mods-available/ssl.load .
ln -s ../mods-available/ssl.conf .
ln -s ../mods-available/socache_shmcb.load .

Activate the new VHost and restart Apache:

cd /etc/apache2/sites-enabled/
ln -s ../sites-available/dso.<yourexchange>.conf .
/etc/init.d/apache2 restart

Connect to Trust Deposit liquidity network

Trust Deposit DSO markets must have minimum nominal set to 0.01.
You can connect either to the testnet DSO using testnet Bitcoin or to the production DSO. For a testnet connection register an account with https://tf-test.draglet.com, for production register at https://www.trust-deposit.net and get KYC approval. In the script below replace URL 'https://dso.trust-deposit.net' with 'https://tf-test.draglet.com' and client name 'trust-deposit' with 'tf-test' for a testnet connection.
After registering for an Trust Deposit account request a client certificate for each new market from certificates@draglet.com. Please include the information, that you want to connect to the Trust Deposit DSO (test or production). Send your registered Trust Deposit User as well as the dso subdomain dso.<your_exchange> and the the market your are connecting in your request.
Check the next free id in table exchange. The exchange id is referred to as <exchange_id> in the scripts below.

INSERT INTO  `draglet`.`exchange` (
`id` ,
`nostro_accounts_holder_id` ,
`fee_difference_sponsor_id` ,
`name` ,
`base_path` ,
`driver` ,
`client_name`
)
VALUES (
'<exchange_id>',  '<nostro_account_holder_id>',  '<nostro_account_holder_id>',  '<new-client>',  'https://dso.trust-deposit.net',  'dso',  'trust-deposit'
);
INSERT INTO  `draglet`.`exchange_market` (
`id` ,
`exchange_id` ,
`market_ident` ,
`nominal_currency` ,
`limit_currency`
)
VALUES (
'<exchange_id>',  '<exchange_id>',  'BTC-EUR',  'BTC',  'EUR'
);
INSERT INTO  `draglet`.`market_conversion` (
`id` ,
`exchange_market_id` ,
`market_id` ,
`active` ,
`nominal_converter_category_id` ,
`limit_converter_category_id` ,
`nominal_conversion_inverted` ,
`limit_conversion_inverted` ,
`dso_spread`
)
VALUES (
'<exchange_id>',  '<exchange_id>',  '<market_id>',  '1', NULL ,  NULL,  '0',  '0', NULL
);

Connect to another market from your own exchange

You can use this configuration option if you want to share liquidity between 2 or more markets of your exchange. This works best if a EUR or USD market is the liquidity distributor with other markets getting instant fiat conversion through the DSO. The id of the distributing market is referred to as <dist_market_id> in the scripts below.
If a market is distributing liquidity to several other markets of the same exchange it identifies with a different client certificate for each connection. To connect your new market to an existing market from your own exchange you need two certificates from certificates@draglet.com: The one expained in 5.3 and another one to connect the existing market to your new market. This second client-name is referred to as <dist-client> in the scripts below.
Store the certificate in /home/certs/client-certs.
Find the chart category that provides the conversion rate between the previously existing market to the new one. For each fiat currency that is created the charting engine will automatically create the categories FX_EUR_<new> and FX_USD_<new>. Find the key in the database table chart_category (referred to as <chart_category_id>).
Register a user to become the nostro account holder of this new connection of your previously existing market. The user id is referred to as <dist_nostro_account_holder_id> in the scripts below.
Check the 2 next free ids in table exchange. The exchange ids are referred to as <exchange_id> and <dist_exchange_id> in the scripts below.
Now insert two DSO connections. One from the new market to the previously existing market and one from the previously existing market to the new one. The scripts assume that the distributing market is BTC-EUR. Replace EUR with USD if your central market runs on USD :

INSERT INTO  `draglet`.`exchange` (
`id` ,
`nostro_accounts_holder_id` ,
`fee_difference_sponsor_id` ,
`name` ,
`base_path` ,
`driver` ,
`client_name`
)
VALUES (
'<exchange_id>',  '<nostro_account_holder_id>',  '<nostro_account_holder_id>',  '<new-client>',  'https://dso.<your_exchange>',  'dso',  '<dist-client>'
);
INSERT INTO  `draglet`.`exchange_market` (
`id` ,
`exchange_id` ,
`market_ident` ,
`nominal_currency` ,
`limit_currency`
)
VALUES (
'<exchange_id>', '<exchange_id>', 'BTC-EUR', 'BTC', 'EUR'
);
INSERT INTO  `draglet`.`market_conversion` (
`id` ,
`exchange_market_id` ,
`market_id` ,
`active` ,
`nominal_converter_category_id` ,
`limit_converter_category_id` ,
`nominal_conversion_inverted` ,
`limit_conversion_inverted` ,
`dso_spread`
)
VALUES (
'<exchange_id>', '<exchange_id>', '<market_id>', '1', NULL, '<chart_category>', '0', '0', NULL
);
INSERT INTO  `draglet`.`exchange` (
`id` ,
`nostro_accounts_holder_id` ,
`fee_difference_sponsor_id` ,
`name` ,
`base_path` ,
`driver` ,
`client_name`
)
VALUES (
'<dist_exchange_id>',  '<dist_nostro_account_holder_id>',  '<dist_nostro_account_holder_id>',  '<dist-client>',  'https://dso.<your_exchange>',  'dso',  '<new-client>'
);
INSERT INTO  `draglet`.`exchange_market` (
`id` ,
`exchange_id` ,
`market_ident` ,
`nominal_currency` ,
`limit_currency`
)
VALUES (
'<dist_exchange_id>',  '<dist_exchange_id>',  'BTC-EUR',  'BTC',  'EUR'
);
INSERT INTO  `draglet`.`market_conversion` (
`id` ,
`exchange_market_id` ,
`market_id` ,
`active` ,
`nominal_converter_category_id` ,
`limit_converter_category_id` ,
`nominal_conversion_inverted` ,
`limit_conversion_inverted` ,
`dso_spread`
)
VALUES (
'<dist_exchange_id>',  '<dist_exchange_id>',  '<dist_market>',  '1', NULL ,  NULL,  '0',  '0', NULL
);


Colored Coins (Open Assets)

Python 3.4

Make sure Python 3.4 and Pip is installed.

apt-get install python3.4 python3-pip

Run a bitcoind with txindex

1. Setup an additional bitcoind service as /etc/service/daemon-btcd-cc
2. Configure the run script to use an alternative config directory using

-datadir=/home/cryptodaemon/.bitcoin-cc/

3. Create the alternative datadir and use a bitcoin.conf file like this:

testnet=1
rpcthreads=20
rpcuser=bitcoinrpc
rpcpassword=<generate-a-new-40-char-passphrase>
port=6035
rpcport=6036
txindex=1
server=1

4. Start the bitcoind and let it sync.


Install colorcore and dependencies

cd /home/cryptodaemon
git clone https://github.com/OpenAssets/colorcore.git
cd colorcore
pip3 install --upgrade -r requirements.txt

Configure colorcore

Edit /home/cryptodaemon/colorcore/config.ini:

[general]
# The following blockchain providers are supported:
# - bitcoind (default): Connects to Bitcoin Core
# - chain.com: Connects to the chain.com API
# - chain.com+bitcoind: Connects to the chain.com API, and uses Bitcoin Core for the local wallet
#
#blockchain-provider=bitcoind

[environment]
# For MainNet
#version-byte=0
#p2sh-version-byte=5                                                                                                                                                                                                                      
#asset-version-byte=23                                                                                                                                                                                                                    
#dust-limit=600                                                                                                                                                                                                                            
#default-fees=30000                                                                                                                                                                                                                        

# For TestNet
version-byte=111
p2sh-version-byte=196
asset-version-byte=115
dust-limit=600
default-fees=30000

[cache]
# Path of the cache file (use :memory: to disable)
#
path=cache.db

[rpc]
# The port on which to expose the Colorcore RPC interface
#
port=6060

[bitcoind]
# Replace username, password and port with the username, password and port for Bitcoin Core
# The default port is 8332 in MainNet and 18332 in TestNet
#
rpcurl=http://bitcoinrpc:<rpc-password-from-bitcoin.conf>@localhost:6036

[chain.com]
# Enable those settings to use the lightweight mode (chain.com blockchain provider)
#
#base-url=https://api.chain.com/v1/bitcoin/
#api-key-id=<get an API key from chain.com>
#secret=<get an API serect from chain.com>

Create service for colorcore daemon

Create the service directory and stop the service.

cd /etc/service
mkdir daemon-coco
svc -d daemon-coco

Create the run script /etc/service/daemon-coco/run.

#!/bin/bash

cd /home/cryptodaemon/colorcore && exec python3 colorcore.py server

Make it executable and start the service:

chmod +x daemon-coco/run
svc -u daemon-coco

Enable license option in cxAdmin

Enable the license key "assets" in cxAdmin.

Configure colorcore in cxWallet

Add to parameters.yml in cxWallet:

    colorcore:
        port: 6036
        username: bitcoinrpc
        password: <rpc-password-from-bitcoin.conf>
        colorport: 6060