The monero faucet can be used as stagenet
faucet or as testnet
faucet.
A faucet in general accepts a monero wallet address and returns a fraction of its own wallet's balance to the given wallet.
Running faucets based on this project can be found at
Visit us at https://community.xmr.to.
These instructions will get you a copy of the faucet up and running on your local machine for development and testing purposes.
See deployment for notes on how to deploy the project on a live system.
Before you even start to use docker-compose to run a faucet locally, you should make a copy of docker-compose-template.yml
.
cp docker-compose-template.yml docker-compose.yml
In docker-compose.yml
you will find some settings, you should be familiar with (default settings refer to docker-compose.yml
, not settings.py
):
- faucet specific
FACTOR_BALANCE
(default:10
)- The factor by which the wallet's balance is divided. Determines the amount to pay to the given address.
WALLET_HOST
(default:localhost
)- IP or URL to the
monero -wallet-rpc
(seemonero-rpc
service)
- IP or URL to the
WALLET_PORT
(default:38083
)- RPC port of the
monero -wallet-rpc
(seemonero-rpc
service)
- RPC port of the
DAEMON_HOST
(default:node.xmr.to
)- IP or URL to
monerod
- IP or URL to
DAEMON_PORT
(default:38081
)- RPC port of
monerod
- RPC port of
DEFAULT_MIXIN
(default:10
)- mixin to be used when making transactions (
ring size = mixin + 1
)
- mixin to be used when making transactions (
FAUCET_PORT
(default:8000
)- Published port of the faucet
- If changed, also modify
- exposed port in
docker-compose.yml
command
indocker-compose.yml
torunserver 0.0.0.0:<your_port>
- exposed port in
- service/project specific
RATELIMIT_ENABLE
(default:True
)- switches on/off rate limitation on the
transactions/
endpoint. - not working locally, since
django-ratelimit
is configured to readheader:x-real-ip
instead ofip
.- if set to
ip
,django-ratelimit
tries to readremote_addr
. - A Middleware could be added to modify
remote_addr
and always useip
in thedjango-ratelimit
configuration.
- if set to
- Makes use of
django-ratelimit
.
- switches on/off rate limitation on the
ONCE_EVERY_N_MINUTE
(default:5
)- configures the faucet's rate limitation on API endpoint
transactions/
to once pern
minutes wheren=ONCE_EVERY_N_MINUTE
.
- configures the faucet's rate limitation on API endpoint
MAXIMUM_PAYOUT
(default:1
)- sets the maximum XMR to pay to the user to
1 XMR
- This was implemented due to the fact, that someone was draining the faucet with a script.
- sets the maximum XMR to pay to the user to
DEBUG
(default:True
)- Should be set to
False
in production
- Should be set to
SECRET_KEY
(default:<some_secret_key>
)- This value should be changed to something sensible in production.
MONERO_ENDPOINT
(default:/
)- Is only changed when several faucets are served by one single proxy server (like nginx).
- See deployment for further information.
CACHE_URL
(default:locmemcache://
)- URL to cache
locmemcache://
uses the local Django cache- See 'Starting the faucet' for use with redis.
- Makes use of
django-environ
.
- URL to cache
DATABASE_URL
(default:sqlite://
)- URL to database
sqlite://
creates an in-memory sqlite databasesqlite:////data/db.develop
creates a sqlite database file calleddb.devlop
- See 'Starting the faucet' for use with postgres.
- Makes use of
django-environ
.
- URL to database
A monero-wallet-rpc
docker image is hosted here. The source can be found here.
The service monero-rpc
does not publish its port (not listening on host's localhost). The port is just exposed, which makes it available in the faucet
service, since they are hosted within the same docker
/docker-compose
network.
Modify monero-rpc
service in docker-compose.yml
.
USER_ID
(default:1000
)- Can be set to whatever
uid
the wallet folder is owned by.- Within the docker container a user (with the given
uid=USER_ID
) is created.
- Within the docker container a user (with the given
- Obviousy only works, if
uid
is available.
- Can be set to whatever
LOG_LEVEL
- verbosity level of
monero-wallet-rpc
log messages
- verbosity level of
- stagenet
--stagenet
--wallet-file <stagenet_wallet>
--password-file <stagenet_wallet_password_file>
- Adapt the path to your monero stagenet wallet
<stagenet_wallet>
. DAEMON_PORT=38081
(or whatever port your daemon is listening to)wallet_port=38083
(or whatever port yout RPC should be listening on)
- testnet
--testnet
--wallet-file <testnet_wallet>
--password-file <testnet_wallet_password_file>
- Adapt the path to your monero testnet wallet
<testnet_wallet>
. DAEMON_PORT=28081
(or whatever port your daemon is listening to)wallet_port=28083
(or whatever port yout RPC should be listening on)
The faucet project makes use of docker
and docker-compose
.
The following tools should be installed to make it work locally:
docker
docker-compose
The faucet can be started like this
docker-compose up -d --build
The above command starts the faucet
service as well as a monero-wallet-rpc
server (as defined within docker-compose.yml
).
It also makes sure, the service's image is built from scratch (--build
) and the services (docker containers) are started in the background (-d
, daemonized).
The local development environment's (Dockerfile
) docker base image (faucet
service) is based on python:3.6
(docker-compose-template.yml
).
For production (prod.Dockerfile
) docker base image(faucet
service) should be based on python:3.6-alpine
(docker-compose-prod.yml
). Please see deployment for more information.
Have a look at the logs:
docker-compose log -f
docker-compose log -f faucet
(onlyfaucet
service)
Stop services:
docker-compose rm -s -f
docker-compose rm -s -f faucet
(onlyfaucet
service)
The default database (docker-compose-template.yml
) is sqlite
.
Using the setting DATABASE_URL
the database can be easily changed.
-
DATABASE_URL=postgresql://postgres:postgres@postgres:5432/transactions
-
DATABASE_URL=sqlite:////data/db.develop
-
sqlite
- uncomment
sqlite
independs_on
(indocker-compose.yml
) - uncomment
sqlite
DATABASE_URL
- comment
postgres
DATABASE_URL
- comment
postgres
independs_on
(indocker-compose.yml
) - comment the
postgres
service (indocker-compose.yml
) - comment the
volumes
(indocker-compose.yml
)
- uncomment
-
postgres
- comment
sqlite
independs_on
(indocker-compose.yml
) - comment
sqlite
DATABASE_URL
- uncomment
postgres
DATABASE_URL
- uncomment
postgres
independs_on
(indocker-compose.yml
) - uncomment the
postgres
service (indocker-compose.yml
) - uncomment the
volumes
(indocker-compose.yml
)
- comment
In the same manner the cache can be configured.
CACHE_URL=rediscache://redis:6379/1?CLIENT_CLASS=django_redis.client.DefaultClient
With its default configuration the faucet listens on port 8000
.
Tests can be run using the script
start_local_tests.sh
This script spins up a docker container and runs the tests within this specific environment.
Have a look at docker-compose-testing.yml
for further details.
Of course, it is also possible to run the faucet
service and enter the container using docker-compose exec faucet bash
.
Then you should be able to activate and enter the virtual environment with pipenv shell
.
From here on, it is possible to run Django commands like python manage.py ...
.
The source code is formatted using black --line-length 79
.
For the deployment we recommend using alpine
as docker base image.
prod.Dockerfile
makes use of this - Locally such an environment can be started with docker-compose-prod.yml
as docker-compose configuration file.
docker-compose -f docker-compose-prod.yml up -d --build
In this case DEBUG
should be set to False
'
Another command
line within docker-compose.yml
can be used to let the faucet be served by uWSGI
.
In this case, comment the command
containing runserver 0.0.0.0...
.
The uWSGI
server listens on port FAUCET_PORT
.
STATIC_ROOT = "/data/static/"
and uWSGI
is configured to serve statc content like this --static-map /static/=/data/static/
.
There might be the need to run stagenet
and testnet
faucets behind the same nginx proxy.
In this case it is recommended to let the faucet be served by uWSGI
.
This requires to differentiate
- API calls
- static content requests between the two faucets.
Therefore MONERO_ENDPOINT
was introduced. This setting defines a URL prefix, that is used when the client talks to the backend.
MONERO_ENDPOINT
modifies the following settings:
- URL to static content in
index.html
- URL to
transactions/
API endpoint inindex.html
by modifiyingSTATIC_URL
insettings.py
.
MONERO_ENDPOINT
should be the same as the appropriate location block in the nginx configuration.
Within the nginx location block the prefixed URL should be stripped of MONERO_ENDPOINT
again, since uWSGI
is configured to just serve static contents
- With
MONERO_ENDPOINT=/
STATIC_URL
becomes/static/
index.html
/transactions/
/static/fonts/fonts.css
- With
MONERO_ENDPOINT=/faucet/stagenet/
STATIC_URL
becomes/faucet/stagenet/static/
index.html
/faucet/stagenet/transactions/
/faucet/stagenet/static/fonts/fonts.css
...
- With
MONERO_ENDPOINT=/faucet/testnet/
STATIC_URL
becomes/faucet/testnet/static/
index.html
/faucet/testnet/transactions/
/faucet/testnet/static/fonts/fonts.css
...
nginx could be configured like this:
set $upstream_faucet_testnet some_ip_url_dns_to_the_testnet_faucet:8000;
location ~ ^/faucet/testnet/ {
if ($request_method !~ ^(GET|POST|HEAD|OPTIONS)$) {
return 405;
}
# forwarding
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass $http_upgrade;
# use the complete $request_uri for rewriting
rewrite ^ $request_uri;
# remove /faucet/testnet/
# take the remaining content and put it into $uri
rewrite ^/faucet/testnet/(.*) /$1 break; # add / before $1 to avoid zero length $uri
return 400; #if the second rewrite does not match
proxy_pass http://$upstream_faucet_testnet$uri;
}
Eventually, this setup requests the backend with /transactions/
instead of /faucet/testnet/transactions/
, which is the configured URL.
Also static content will be requested from /static/fonts/fonts.css
instead of /faucet/testnet/fonts/fonts.css
, like the uWSGI
configuration defines.
The services are run within docker containers.
The faucet
service is backed by python3.6
.
The virtual environment for python is created and maintained with pipenv
.
Specific versions are defined within Pipfile
.
django-environ
is used to to extract database URLs as well as cache URLs.django-ratelimit
is used to rate throttle API endpoints.djangorestframework
is used to create a REST API.
We use SemVer for versioning. For the versions available, see the tags on this repository.
- Norman Moeschter-Schenck - Initial work - normoes
See also the list of contributors who participated in this project.
This project is licensed under the Apache 2.0 License - see the LICENSE file for details
makemigrations
could, in some cases, be interactive (e.g. renaming a model field).
Then, the faucet
container will not start successfully.
- Leave the
faucet
service in its unsuccessful state
# enter the running faucet service container
docker-compose exec faucet bash
# enter the virtual environment
pipenv shell
# run makemigrations manually
python manage.py makemigrations # interactive