App Submission: Monero Node (#690)

Co-authored-by: nmfretz <nmfretz@gmail.com>
This commit is contained in:
Deverick 2024-06-25 18:10:24 -05:00 committed by GitHub
parent 417d214271
commit e70fb53470
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 284 additions and 0 deletions

0
monero/data/app/.gitkeep Normal file
View File

View File

View File

78
monero/docker-compose.yml Normal file
View File

@ -0,0 +1,78 @@
version: "3.7"
services:
app_proxy:
environment:
APP_HOST: monero_server_1
APP_PORT: 9976
server:
image: deverickapollo/umbrel-monero:v1.0.8@sha256:4cfb0a9b852175b73c9c3cb37771eb28c20fd21140bb85a98726dd6d09ee03f9
depends_on: [monerod]
restart: on-failure
expose:
- "9976"
volumes:
- ${APP_DATA_DIR}/data/app:/data # volume to persist advanced settings json
- ${APP_MONERO_DATA_DIR}:/monero/.monero # volume to persist bitmonero.conf
environment:
PORT: "9976"
MONERO_HOST: "${APP_MONERO_NODE_IP}"
MONERO_P2P_PORT: "${APP_MONERO_P2P_PORT}"
MONERO_RPC_PORT: "${APP_MONERO_RPC_PORT}"
MONERO_RESTRICTED_RPC_PORT: "${APP_MONERO_RESTRICTED_RPC_PORT}"
MONERO_DEFAULT_NETWORK: "${MONERO_DEFAULT_NETWORK}"
MONERO_RPC_USER: "${APP_MONERO_RPC_USER}"
MONERO_RPC_PASSWORD: "${APP_MONERO_RPC_PASS}"
MONERO_RPC_HIDDEN_SERVICE: "${APP_MONERO_RPC_HIDDEN_SERVICE}"
MONERO_P2P_HIDDEN_SERVICE: "${APP_MONERO_P2P_HIDDEN_SERVICE}"
DEVICE_DOMAIN_NAME: "${DEVICE_DOMAIN_NAME}"
MONEROD_IP: "${APP_MONERO_NODE_IP}"
TOR_PROXY_IP: "${APP_MONERO_TOR_PROXY_IP}"
TOR_PROXY_PORT: "9050"
TOR_PROXY_CONTROL_PORT: "9051"
TOR_PROXY_CONTROL_PASSWORD: "moneyprintergobrrr"
I2P_DAEMON_IP: "${APP_MONERO_I2P_DAEMON_IP}"
I2P_DAEMON_PORT: "7656"
networks:
default:
ipv4_address: $APP_MONERO_IP
monerod:
user: "1000:1000"
restart: unless-stopped
stop_grace_period: 15m
command: "${APP_MONERO_COMMAND}"
image: ghcr.io/sethforprivacy/simple-monerod:v0.18.3.3@sha256:4e07ca4119cd34d61684c44151296535cb9ba674e081d0a622432be4ac51c2c9
ports:
- "${APP_MONERO_P2P_PORT}:${APP_MONERO_P2P_PORT}"
- "${APP_MONERO_RPC_PORT}:${APP_MONERO_RPC_PORT}"
volumes:
- "${APP_MONERO_DATA_DIR}:/home/monero/.bitmonero"
networks:
default:
ipv4_address: $APP_MONERO_NODE_IP
tor:
image: getumbrel/tor:0.4.7.8@sha256:2ace83f22501f58857fa9b403009f595137fa2e7986c4fda79d82a8119072b6a
user: "1000:1000"
restart: on-failure
volumes:
- ${APP_DATA_DIR}/torrc:/etc/tor/torrc:ro
- ${TOR_DATA_DIR}:/data
environment:
HOME: "/tmp"
networks:
default:
ipv4_address: "${APP_MONERO_TOR_PROXY_IP}"
# i2pd_daemon:
# image: purplei2p/i2pd:release-2.44.0@sha256:d154a599793c393cf9c91f8549ba7ece0bb40e5728e1813aa6dd4c210aa606f6
# user: "root"
# command: --sam.enabled=true --sam.address=0.0.0.0 --sam.port=7656 --loglevel=error
# restart: on-failure
# volumes:
# - ${APP_DATA_DIR}/data/i2pd:/home/i2pd/data
# networks:
# default:
# ipv4_address: "${APP_MONERO_I2P_DAEMON_IP}"

95
monero/exports.sh Normal file
View File

@ -0,0 +1,95 @@
export APP_MONERO_IP="10.21.22.178"
export APP_MONERO_NODE_IP="10.21.21.179"
export APP_MONERO_TOR_PROXY_IP="10.21.21.180"
export APP_MONERO_I2P_DAEMON_IP="10.21.21.181"
export APP_MONERO_DATA_DIR="${EXPORTS_APP_DIR}/data/monero"
export APP_MONERO_RPC_PORT="18081"
export APP_MONERO_RESTRICTED_RPC_PORT="18089"
export APP_MONERO_P2P_PORT="18080"
export APP_MONERO_TOR_PORT="9901"
#temporarily set to mainnet
MONERO_NETWORK="mainnet"
MONERO_CHAIN="mainnet"
MONERO_ENV_FILE="${EXPORTS_APP_DIR}/.env"
{
MONERO_APP_CONFIG_FILE="${EXPORTS_APP_DIR}/data/app/monero-config.json"
if [[ -f "${MONERO_APP_CONFIG_FILE}" ]]
then
monero_app_network=$(jq -r '.network' "${MONERO_APP_CONFIG_FILE}")
case $monero_app_network in
"mainnet")
MONERO_NETWORK="mainnet";;
"testnet")
MONERO_NETWORK="testnet";;
"stagenet")
MONERO_NETWORK="stagenet";;
esac
fi
} > /dev/null || true
if [[ ! -f "${MONERO_ENV_FILE}" ]]; then
if [[ -z "${MONERO_NETWORK}" ]]; then
MONERO_NETWORK="mainnet"
fi
if [[ -z ${MONERO_RPC_USER+x} ]] || [[ -z ${MONERO_RPC_PASS+x} ]] || [[ -z ${MONERO_RPC_AUTH+x} ]]; then
MONERO_RPC_USER="monero"
MONERO_RPC_DETAILS=$("${EXPORTS_APP_DIR}/scripts/rpcauth.py" "${MONERO_RPC_USER}")
MONERO_RPC_PASS=$(echo "$MONERO_RPC_DETAILS" | tail -1)
MONERO_RPC_AUTH=$(echo "$MONERO_RPC_DETAILS" | head -2 | tail -1 | sed -e "s/^rpc-login=//")
fi
echo "export APP_MONERO_NETWORK='${MONERO_NETWORK}'" > "${MONERO_ENV_FILE}"
echo "export APP_MONERO_RPC_USER='${MONERO_RPC_USER}'" >> "${MONERO_ENV_FILE}"
echo "export APP_MONERO_RPC_PASS='${MONERO_RPC_PASS}'" >> "${MONERO_ENV_FILE}"
echo "export APP_MONERO_RPC_AUTH='${MONERO_RPC_AUTH}'" >> "${MONERO_ENV_FILE}"
fi
. "${MONERO_ENV_FILE}"
# Make sure we don't persist the original value in .env if we have a more recent
# value from the app config
{
if [[ ! -z ${MONERO_NETWORK+x} ]] && [[ "${MONERO_NETWORK}" ]] && [[ "${APP_MONERO_NETWORK}" ]]
then
APP_MONERO_NETWORK="${MONERO_NETWORK}"
fi
} > /dev/null || true
if [[ "${APP_MONERO_NETWORK}" == "mainnet" ]]; then
MONERO_CHAIN="mainnet"
elif [[ "${APP_MONERO_NETWORK}" == "testnet" ]]; then
MONERO_CHAIN="testnet"
export APP_MONERO_RPC_PORT="28081"
export APP_MONERO_P2P_PORT="28080"
elif [[ "${APP_MONERO_NETWORK}" == "stagenet" ]]; then
MONERO_CHAIN="stagenet"
export APP_MONERO_RPC_PORT="38081"
export APP_MONERO_P2P_PORT="38080"
else
echo "Warning (${EXPORTS_APP_ID}): Monero Network '${APP_MONERO_NETWORK}' is not supported"
fi
export MONERO_DEFAULT_NETWORK="${MONERO_CHAIN}"
BIN_ARGS=()
BIN_ARGS+=( "--rpc-bind-port=${APP_MONERO_RPC_PORT}" )
BIN_ARGS+=( "--rpc-bind-ip=0.0.0.0" )
BIN_ARGS+=( "--confirm-external-bind" )
BIN_ARGS+=( "--rpc-login=\"${APP_MONERO_RPC_AUTH}\"" )
export APP_MONERO_COMMAND=$(IFS=" "; echo "${BIN_ARGS[@]}")
# echo "${APP_MONERO_COMMAND}"
rpc_hidden_service_file="${EXPORTS_TOR_DATA_DIR}/app-${EXPORTS_APP_ID}-rpc/hostname"
p2p_hidden_service_file="${EXPORTS_TOR_DATA_DIR}/app-${EXPORTS_APP_ID}-p2p/hostname"
export APP_MONERO_RPC_HIDDEN_SERVICE="$(cat "${rpc_hidden_service_file}" 2>/dev/null || echo "notyetset.onion")"
export APP_MONERO_P2P_HIDDEN_SERVICE="$(cat "${p2p_hidden_service_file}" 2>/dev/null || echo "notyetset.onion")"

26
monero/hooks/pre-start Executable file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
# Delay booting Monero until the RPC and P2P Tor Hidden Services are ready
HIDDEN_SERVICE_FILE="${TOR_DATA_DIR}/app-${APP_ID}-rpc/hostname"
if [[ -f "${HIDDEN_SERVICE_FILE}" ]]; then
exit
fi
"${UMBREL_ROOT}/scripts/app" compose "${APP_ID}" up --detach monerod
"${UMBREL_ROOT}/scripts/app" compose "${APP_ID}" up --detach tor
echo "App: ${APP_ID} - Generating Tor Hidden Service..."
for attempt in $(seq 1 100); do
if [[ -f "${HIDDEN_SERVICE_FILE}" ]]; then
echo "App: ${APP_ID} - Hidden service file created successfully!"
break
fi
sleep 0.1
done
if [[ ! -f "${HIDDEN_SERVICE_FILE}" ]]; then
echo "App: ${APP_ID} - Hidden service file wasn't created"
fi

47
monero/scripts/rpcauth.py Executable file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from argparse import ArgumentParser
from base64 import urlsafe_b64encode
from binascii import hexlify
from getpass import getpass
from os import urandom
import hmac
def generate_salt(size):
"""Create size byte hex salt"""
return hexlify(urandom(size)).decode()
def generate_password():
"""Create 32 byte b64 password"""
return urlsafe_b64encode(urandom(32)).decode('utf-8')
def password_to_hmac(salt, password):
m = hmac.new(bytearray(salt, 'utf-8'), bytearray(password, 'utf-8'), 'SHA256')
return m.hexdigest()
def main():
parser = ArgumentParser(description='Create login credentials for a JSON-RPC user')
parser.add_argument('username', help='the username for authentication')
parser.add_argument('password', help='leave empty to generate a random password or specify "-" to prompt for password', nargs='?')
args = parser.parse_args()
if not args.password:
args.password = generate_password()
elif args.password == '-':
args.password = getpass()
# Create 16 byte hex salt
# salt = generate_salt(16)
# password_hmac = password_to_hmac(salt, args.password)
print('String to be appended to monerod.conf:')
# Replaced rpcauth with rpc-login to support monero daemon rpc login format (username:password) instead of (username:salt$hash)
print('rpc-login={0}:{1}'.format(args.username, args.password))
print('Your password:\n{0}'.format(args.password))
if __name__ == '__main__':
main()

13
monero/torrc.template Normal file
View File

@ -0,0 +1,13 @@
SocksPort 0.0.0.0:9050
ControlPort 0.0.0.0:9051
CookieAuthentication 1
CookieAuthFileGroupReadable 1
HashedControlPassword 16:39AF5EEFA4FC1D986022FDFB13663669FE50FB6DE9A3B4FE4FC7D82010 # moneyprintergobrrr
# MONERO Core P2P Hidden Service
HiddenServiceDir /data/app-$APP_ID-p2p
HiddenServicePort $APP_MONERO_P2P_PORT $APP_MONERO_NODE_IP:$APP_MONERO_TOR_PORT
# MONERO Core RPC Hidden Service
HiddenServiceDir /data/app-$APP_ID-rpc
HiddenServicePort $APP_MONERO_RPC_PORT $APP_MONERO_NODE_IP:$APP_MONERO_RPC_PORT

25
monero/umbrel-app.yml Normal file
View File

@ -0,0 +1,25 @@
manifestVersion: 1.1
id: monero
category: finance
name: Monero Node
version: "0.18.3.3"
tagline: Run a monero node
description: >-
Run your monero node and independently store and validate every single Monero transaction with it.
This is a full node that will download the entire Monero blockchain and store it on your Umbrel.
This is the most secure way to run a Monero node, but it will take a long time to sync and will require a lot of storage space.
developer: deverickapollo
website: https://www.getmonero.org/
dependencies: []
repo: https://github.com/deverickapollo/umbrel-monero
support: https://github.com/deverickapollo/umbrel-monero/issues
port: 9976
submitter: deverickapollo
submission: https://github.com/getumbrel/umbrel-apps/pull/690
gallery:
- 1.jpg
- 2.jpg
- 3.jpg
path: ""
defaultPassword: ""
releaseNotes: ""