From af87a089812465f26ca539eb21f8e2c07b0fd895 Mon Sep 17 00:00:00 2001 From: Ronald Loyko <108372764+ronaldloyko@users.noreply.github.com> Date: Sat, 1 Oct 2022 06:39:31 +0300 Subject: [PATCH] feat: add btcpayserver (#743) * feat: add btcpayserver * feat: add logo for btcpayserver * fix: mention HTTPS in the instructions * fix: add thunderhub volume to main app * fix: mention nginx configuration changes in instructions --- public/v4/apps/btcpayserver.yml | 483 +++++++++++++++++++++++++++++++ public/v4/logos/btcpayserver.png | Bin 0 -> 13736 bytes 2 files changed, 483 insertions(+) create mode 100644 public/v4/apps/btcpayserver.yml create mode 100644 public/v4/logos/btcpayserver.png diff --git a/public/v4/apps/btcpayserver.yml b/public/v4/apps/btcpayserver.yml new file mode 100644 index 0000000..22078f2 --- /dev/null +++ b/public/v4/apps/btcpayserver.yml @@ -0,0 +1,483 @@ +captainVersion: 4 +services: + $$cap_appname: + caproverExtra: + containerHttpPort: $$cap_BTCPAY_PORT + image: btcpayserver/btcpayserver:$$cap_BTCPAYSERVER_VERSION + hostname: $$cap_appname.$$cap_root_domain + environment: + BTCPAY_HOST: $$cap_appname.$$cap_root_domain + BTCPAY_POSTGRES: User ID=$$cap_POSTGRES_USER;Host=srv-captain--$$cap_appname-postgres;Port=$$cap_POSTGRES_PORT;Application Name=btcpayserver;Database=btcpayserver$$cap_NBITCOIN_NETWORK + BTCPAY_EXPLORERPOSTGRES: User ID=$$cap_POSTGRES_USER;Host=srv-captain--$$cap_appname-postgres;Port=$$cap_POSTGRES_PORT;Application Name=btcpayserver;MaxPoolSize=80;Database=nbxplorer$$cap_NBITCOIN_NETWORK + BTCPAY_NETWORK: $$cap_NBITCOIN_NETWORK + BTCPAY_BIND: $$cap_BIND_ADDRESS:$$cap_BTCPAY_PORT + BTCPAY_ROOTPATH: $$cap_BTCPAY_ROOTPATH + BTCPAY_DEBUGLOG: $$cap_BTCPAY_DEBUGLOG + BTCPAY_UPDATEURL: $$cap_BTCPAY_UPDATEURL + BTCPAY_DOCKERDEPLOYMENT: 'true' + BTCPAY_CHAINS: $$cap_USED_CHAIN + BTCPAY_BTCEXPLORERURL: http://srv-captain--$$cap_appname-nbxplorer:$$cap_NBXPLORER_PORT/ + BTCPAY_BTCLIGHTNING: type=lnd-rest;server=http://srv-captain--$$cap_appname-lnd:$$cap_LND_REST_LISTEN_PORT/;macaroonfilepath=/etc/lnd_bitcoin/admin.macaroon;allowinsecure=true + BTCPAY_BTCEXTERNALLNDGRPC: server=/;macaroonfilepath=/etc/lnd_bitcoin/admin.macaroon;macaroondirectorypath=/etc/lnd_bitcoin + BTCPAY_BTCEXTERNALLNDREST: server=/lnd-rest/btc/;macaroonfilepath=/etc/lnd_bitcoin/admin.macaroon;macaroondirectorypath=/etc/lnd_bitcoin + BTCPAY_BTCEXTERNALLNDSEEDBACKUP: /etc/lnd_bitcoin/data/chain/bitcoin/$$cap_NBITCOIN_NETWORK/walletunlock.json + BTCPAY_BTCEXTERNALTHUNDERHUB: server=/thub/sso;cookiefile=/etc/lnd_bitcoin_thub_datadir/.cookie + depends_on: + - $$cap_appname-postgres + volumes: + - $$cap_appname-data:/datadir + - $$cap_appname-nbxplorer-data:/root/.nbxplorer + - $$cap_appname-plugins:/root/.btcpayserver/Plugins + - $$cap_appname-lnd-data:/etc/lnd_bitcoin + - $$cap_appname-thub-data:/etc/lnd_bitcoin_thub_datadir + + $$cap_appname-postgres: + caproverExtra: + notExposeAsWebApp: 'true' + dockerfileLines: + - FROM btcpayserver/postgres:$$cap_POSTGRES_VERSION + - CMD ["-c", "random_page_cost=1.0", "-c", "shared_preload_libraries=pg_stat_statements"] + environment: + POSTGRES_HOST_AUTH_METHOD: $$cap_POSTGRES_HOST_AUTH_METHOD + volumes: + - $$cap_appname-postgres:/var/lib/postgresql/data + + $$cap_appname-nbxplorer: + caproverExtra: + notExposeAsWebApp: 'true' + image: nicolasdorier/nbxplorer:$$cap_NBXPLORER_VERSION + environment: + NBXPLORER_NETWORK: $$cap_NBITCOIN_NETWORK + NBXPLORER_BIND: $$cap_BIND_ADDRESS:$$cap_NBXPLORER_PORT + NBXPLORER_TRIMEVENTS: $$cap_NBXPLORER_TRIMEVENTS + NBXPLORER_SIGNALFILESDIR: $$cap_NBXPLORER_SIGNALFILESDIR + NBXPLORER_POSTGRES: User ID=$$cap_POSTGRES_USER;Host=srv-captain--$$cap_appname-postgres;Port=$$cap_POSTGRES_PORT;Application Name=nbxplorer;MaxPoolSize=20;Database=nbxplorer$$cap_NBITCOIN_NETWORK + NBXPLORER_AUTOMIGRATE: $$cap_NBXPLORER_AUTOMIGRATE + NBXPLORER_NOMIGRATEEVTS: $$cap_NBXPLORER_NOMIGRATEEVTS + NBXPLORER_CHAINS: $$cap_USED_CHAIN + NBXPLORER_BTCRPCURL: http://srv-captain--$$cap_appname-bitcoind:$$cap_BITCOIN_RPC_PORT/ + NBXPLORER_BTCNODEENDPOINT: srv-captain--$$cap_appname-bitcoind:$$cap_BITCOIN_NODE_PORT + depends_on: + - $$cap_appname-postgres + volumes: + - $$cap_appname-nbxplorer-data:/datadir + - $$cap_appname-bitcoind-data:/root/.bitcoin + + $$cap_appname-bitcoind: + caproverExtra: + notExposeAsWebApp: 'true' + image: btcpayserver/bitcoin:$$cap_BITCOIN_VERSION + environment: + BITCOIN_NETWORK: $$cap_NBITCOIN_NETWORK + BITCOIN_WALLETDIR: $$cap_BITCOIN_WALLETDIR + BITCOIN_EXTRA_ARGS: | + rpcport=$$cap_BITCOIN_RPC_PORT + rpcbind=$$cap_BIND_ADDRESS:$$cap_BITCOIN_RPC_PORT + rpcallowip=$$cap_BIND_ADDRESS/$$cap_BITCOIN_IP_ALLOWLIST_CIDR + port=$$cap_BITCOIN_NODE_PORT + whitelist=$$cap_BIND_ADDRESS/$$cap_BITCOIN_IP_ALLOWLIST_CIDR + maxmempool=$$cap_BITCOIN_MAX_MEMPOOL + prune=$$cap_BITCOIN_PRUNE + zmqpubrawblock=tcp://$$cap_BIND_ADDRESS:$$cap_BITCOIN_RAW_BLOCK_PUBLICATION_PORT + zmqpubrawtx=tcp://$$cap_BIND_ADDRESS:$$cap_BITCOIN_RAW_TRANSACTION_PUBLICATION_PORT + zmqpubhashblock=tcp://$$cap_BIND_ADDRESS:$$cap_BITCOIN_BLOCK_HASH_PUBLICATION_PORT + rpcauth=$$cap_LND_BITCOIN_RPC_USER:$$cap_LND_BITCOIN_RPC_HASHED_PASSWORD + $$cap_BITCOIN_ADDITIONAL_ARGUMENTS + volumes: + - $$cap_appname-bitcoind-wallet-data:/walletdata + - $$cap_appname-bitcoind-data:/data + + $$cap_appname-lnd: + caproverExtra: + notExposeAsWebApp: 'true' + image: btcpayserver/lnd:$$cap_LND_VERSION + environment: + LND_CHAIN: $$cap_USED_CHAIN + LND_EXTERNALIP: $$cap_appname.$$cap_root_domain + LND_PORT: $$cap_LND_PORT + LND_ALIAS: $$cap_LND_ALIAS + LND_ENVIRONMENT: $$cap_NBITCOIN_NETWORK + LND_READY_FILE: $$cap_LND_READY_FILE + LND_REST_LISTEN_HOST: http://srv-captain--$$cap_appname-lnd:$$cap_LND_REST_LISTEN_PORT + LND_HOST_FOR_LOOP: $$cap_LOOPBACK_ADDRESS:$$cap_LND_LOOP_LISTEN_PORT + LND_EXTRA_ARGS: | + restlisten=srv-captain--$$cap_appname-lnd:$$cap_LND_REST_LISTEN_PORT + rpclisten=$$cap_LOOPBACK_ADDRESS:$$cap_LND_RPC_LISTEN_PORT + rpclisten=srv-captain--$$cap_appname-lnd:$$cap_LND_LOOP_LISTEN_PORT + rpclisten=$$cap_LOOPBACK_ADDRESS:$$cap_LND_LOOP_LISTEN_PORT + bitcoin.node=srv-captain--$$cap_appname-bitcoind + bitcoind.rpchost=srv-captain--$$cap_appname-bitcoind:$$cap_BITCOIN_RPC_PORT + bitcoind.rpcuser=$$cap_LND_BITCOIN_RPC_USER + bitcoind.rpcpass=$$cap_LND_BITCOIN_RPC_PASSWORD + bitcoind.zmqpubrawblock=tcp://srv-captain--$$cap_appname-bitcoind:$$cap_BITCOIN_RAW_BLOCK_PUBLICATION_PORT + bitcoind.zmqpubrawtx=tcp://srv-captain--$$cap_appname-bitcoind:$$cap_BITCOIN_RAW_TRANSACTION_PUBLICATION_PORT + adminmacaroonpath=$$cap_LND_ADMIN_MACAROON_PATH + invoicemacaroonpath=$$cap_LND_INVOICE_MACAROON_PATH + readonlymacaroonpath=$$cap_LND_READ_ONLY_MACAROON_PATH + tlsextradomain=srv-captain--$$cap_appname-lnd + no-rest-tls=$$cap_LND_NO_REST_TLS + protocol.wumbo-channels=$$cap_LND_WUMBO_CHANNELS + autopilot.active=$$cap_LND_AUTOPILOT_ACTIVE + autopilot.maxchannels=$$cap_LND_AUTOPILOT_MAXIMUM_CHANNELS + autopilot.allocation=$$cap_LND_AUTOPILOT_ALLOCATION + $$cap_LND_ADDITIONAL_ARGUMENTS + depends_on: + - $$cap_appname-bitcoind + ports: + - $$cap_LND_PORT:$$cap_LND_PORT + volumes: + - $$cap_appname-lnd-data:/data + - $$cap_appname-lnd-loop-bitcoin-data:/root/.loop/$$cap_NBITCOIN_NETWORK + - $$cap_appname-bitcoind-data:/deps/.bitcoin + - $$cap_appname-nbxplorer-data:/root/.nbxplorer + + $$cap_appname-thub: + caproverExtra: + notExposeAsWebApp: 'true' + image: apotdevin/thunderhub:$$cap_THUB_VERSION + environment: + NO_VERSION_CHECK: $$cap_THUB_NO_VERSION_CHECK + COOKIE_PATH: $$cap_THUB_COOKIE_PATH + ACCOUNT_CONFIG_PATH: $$cap_THUB_ACCOUNT_CONFIG_PATH + SSO_SERVER_URL: srv-captain--$$cap_appname-lnd:$$cap_LND_LOOP_LISTEN_PORT + SSO_MACAROON_PATH: $$cap_THUB_SSO_MACAROON_PATH + SSO_CERT_PATH: $$cap_THUB_SSO_CERT_PATH + NO_CLIENT_ACCOUNTS: $$cap_THUB_NO_CLIENT_ACCOUNTS + LOG_LEVEL: $$cap_THUB_LOG_LEVEL + LOGOUT_URL: $$cap_THUB_LOGOUT_URL + volumes: + - $$cap_appname-lnd-data:/etc/lnd + - $$cap_appname-thub-data:/data + depends_on: + - $$cap_appname-lnd + +caproverOneClickApp: + instructions: + start: |- + BTCPay Server is a free, open-source & self-hosted bitcoin payment gateway. + It allows self-sovereign individuals and businesses to accept bitcoin payments online or in person without any fees. + + This will deploy: + - BTCPay Server application + - `bitcoind` as Bitcoin full node (pruned to 50 GB by default) + - `lnd` as Lightning node + - `thunderhub` for managing the Lightning node + + Please note that features like SSH access and Onion service have been omitted to keep deployment simple. + You may need to open the port `9735` in your firewall. + end: |- + BTCPay Server has been successfully deployed! + Please change the following settings before using the service: + 1. Go to the settings for `$$cap_appname` + 2. Enable **Websocket Support** + 3. Enable **HTTPS** + 4. Click on **Edit Default Nginx Configurations** and paste the following content before the last closing bracket "}": + ``` + location ~* ^/(lnrpc|routerrpc)\. { + grpc_read_timeout 6000s; + grpc_send_timeout 6000s; + grpc_pass grpcs://srv-captain--$$cap_appname-lnd:$$cap_LND_LOOP_LISTEN_PORT; + } + location /lnd-rest/btc/ { + rewrite ^/lnd-rest/btc/(.*) /$1 break; + proxy_pass http://srv-captain--$$cap_appname-lnd:$$cap_LND_REST_LISTEN_PORT/; + } + + location /thub { + proxy_pass http://srv-captain--$$cap_appname-thub:3000/thub; + } + ``` + Now you can access it at `https://$$cap_appname.$$cap_root_domain` + It will take some time to synchronize the Bitcoin full node. + You should also observe the app logs from time to time. + displayName: BTCPay Server + isOfficial: true + description: Free, open-source & self-hosted, Bitcoin payment processor. + documentation: https://docs.btcpayserver.org + variables: + - id: $$cap_BIND_ADDRESS + label: General | Bind Address + description: Address to bind the services. + defaultValue: '0.0.0.0' + validRegex: /.{1,}/ + - id: $$cap_LOOPBACK_ADDRESS + label: General | Loopback Address + description: Loopback address. Should not be changed. + defaultValue: '127.0.0.1' + validRegex: /.{1,}/ + - id: $$cap_BTCPAYSERVER_VERSION + label: General | BTCPay Server Version + description: Check out their valid tags at https://hub.docker.com/r/btcpayserver/btcpayserver/tags + defaultValue: '1.6.11' + validRegex: /.{1,}/ + - id: $$cap_POSTGRES_VERSION + label: General | PostgreSQL Version + description: Check out their valid tags at https://hub.docker.com/r/btcpayserver/postgres/tags + defaultValue: '13.7' + validRegex: /.{1,}/ + - id: $$cap_NBXPLORER_VERSION + label: General | NBXplorer Version + description: Check out their valid tags at https://hub.docker.com/r/nicolasdorier/nbxplorer/tags + defaultValue: '2.3.38' + validRegex: /.{1,}/ + - id: $$cap_BITCOIN_VERSION + label: General | Bitcoin Node Version + description: Check out their valid tags at https://hub.docker.com/r/btcpayserver/bitcoin/tags + defaultValue: '23.0' + validRegex: /.{1,}/ + - id: $$cap_LND_VERSION + label: General | Lightning Node Version + description: Check out their valid tags at https://hub.docker.com/r/btcpayserver/lnd/tags + defaultValue: v0.15.0-beta + validRegex: /.{1,}/ + - id: $$cap_THUB_VERSION + label: General | Thunderhub Version + description: Check out their valid tags at https://hub.docker.com/r/apotdevin/thunderhub/tags + defaultValue: base-v0.13.11@sha256:248db7508af8d1563f3afdbaec2ffd62e6f1868e30f8f1c3bb514bf8633c44f9 + validRegex: /.{1,}/ + - id: $$cap_NBITCOIN_NETWORK + label: General | Network Type + description: The type of Bitcoin network to use (e.g. `mainnet`, `testnet`, or `regtest`) + defaultValue: mainnet + validRegex: /^(mainnet|testnet|regtest|simnet)$/ + - id: $$cap_USED_CHAIN + label: Explorer | Chain + description: Blockchain to be used. Defaults is `btc` and should **not** be changed. + defaultValue: btc + validRegex: /.{1,}/ + - id: $$cap_POSTGRES_PORT + label: Database | Port + description: Port of the PostgreSQL database host. + defaultValue: 5432 + validRegex: /.{1,}/ + - id: $$cap_POSTGRES_USER + label: Database | User + description: User of the PostgreSQL database. + defaultValue: postgres + validRegex: /.{1,}/ + - id: $$cap_POSTGRES_HOST_AUTH_METHOD + label: Database | Authentication Method + description: Method of authentication for incoming connections in PostgreSQL. + defaultValue: trust + validRegex: /.{1,}/ + - id: $$cap_BTCPAY_ROOTPATH + label: Application | Root Path + description: Root path of the application. + defaultValue: / + validRegex: /.{1,}/ + - id: $$cap_BTCPAY_PORT + label: Application | Port + description: Port of the application host. + defaultValue: 49392 + validRegex: /.{1,}/ + - id: $$cap_BTCPAY_DEBUGLOG + label: Application | Debug Log + description: Log file for debugging information. + defaultValue: btcpay.log + validRegex: /.{1,}/ + - id: $$cap_BTCPAY_UPDATEURL + label: Application | Update URL + description: URL to BTCPay Server releases. + defaultValue: https://api.github.com/repos/btcpayserver/btcpayserver/releases/latest + validRegex: /.{1,}/ + - id: $$cap_NBXPLORER_PORT + label: Explorer | Port + description: Port of the NBXplorer host. + defaultValue: 32838 + validRegex: /.{1,}/ + - id: $$cap_NBXPLORER_TRIMEVENTS + label: Explorer | Trim Events + description: Trim the amount of events in NBXplorer. + defaultValue: 10000 + validRegex: /.{1,}/ + - id: $$cap_NBXPLORER_SIGNALFILESDIR + label: Explorer | Signal Files Directory + description: Path to signal files directory in NBXplorer. + defaultValue: /datadir + validRegex: /.{1,}/ + - id: $$cap_NBXPLORER_AUTOMIGRATE + label: Explorer | Automatic Migrations + description: Whether to enable automatic migrations. + defaultValue: 'true' + validRegex: /^(true|false)$/ + - id: $$cap_NBXPLORER_NOMIGRATEEVTS + label: Explorer | Event Migrations + description: Whether to disable event migrations. + defaultValue: 'true' + validRegex: /^(true|false)$/ + - id: $$cap_BITCOIN_RPC_PORT + label: Bitcoin Node | RPC Port + description: Port of Bitcoin node RPC. + defaultValue: 43782 + validRegex: /.{1,}/ + - id: $$cap_BITCOIN_NODE_PORT + label: Bitcoin Node | Node Port + description: Port of Bitcoin node endpoint. + defaultValue: 39388 + validRegex: /.{1,}/ + - id: $$cap_BITCOIN_WALLETDIR + label: Bitcoin Node | Wallet Directory + description: Path to wallet files directory of the Bitcoin node. + defaultValue: /walletdata + validRegex: /.{1,}/ + - id: $$cap_BITCOIN_MAX_MEMPOOL + label: Bitcoin Node | Maximum Mempool Size + description: Maximum Bitcoin node mempool size in megabytes. + defaultValue: 500 + validRegex: /.{1,}/ + - id: $$cap_BITCOIN_IP_ALLOWLIST_CIDR + label: Bitcoin Node | Allowlist Subnet + description: Whitelist IP subnet using CIDR notation for the Bitcoin node. + defaultValue: '0' + validRegex: /.{1,}/ + - id: $$cap_BITCOIN_PRUNE + label: Bitcoin Node | Prune + description: |- + Configure a disk space on stored blocks of the Bitcoin node, denoted in megabytes. + Default is 50 gigabytes, this will keep around 6 months of blocks. + defaultValue: 50000 + - id: $$cap_BITCOIN_ADDITIONAL_ARGUMENTS + label: Bitcoin Node | Additional Arguments + description: Additional Bitcoin node startup arguments. + - id: $$cap_BITCOIN_RAW_BLOCK_PUBLICATION_PORT + label: Bitcoin Node | Raw Block Publication Port + description: Port of raw block information publisher. + defaultValue: 28332 + validRegex: /.{1,}/ + - id: $$cap_BITCOIN_RAW_TRANSACTION_PUBLICATION_PORT + label: Bitcoin Node | Raw Transaction Publication Port + description: Port of raw transaction information publisher. + defaultValue: 28333 + validRegex: /.{1,}/ + - id: $$cap_BITCOIN_BLOCK_HASH_PUBLICATION_PORT + label: Bitcoin Node | Block Hash Publication Port + description: Port of block hash information publisher. + defaultValue: 28334 + validRegex: /.{1,}/ + - id: $$cap_LND_PORT + label: Lightning Node | Port + description: Port of the Lightning node. + defaultValue: 9735 + validRegex: /.{1,}/ + - id: $$cap_LND_ALIAS + label: Lightning Node | Alias + description: An alias for your Lightning node. + defaultValue: my-awesome-node-$$cap_gen_random_hex(32) + - id: $$cap_LND_READY_FILE + label: Lightning Node | Ready File + description: Path to Bitcoin node ready status indicator file in the Lightning node. + defaultValue: /root/.nbxplorer/btc_fully_synched + validRegex: /.{1,}/ + - id: $$cap_LND_REST_LISTEN_PORT + label: Lightning Node | REST API Listening Port + description: Port of the REST API listener in the Lightning node. + defaultValue: 8080 + validRegex: /.{1,}/ + - id: $$cap_LND_RPC_LISTEN_PORT + label: Lightning Node | RPC Listening Port + description: Port of the RPC listener in the Lightning node. + defaultValue: 10008 + validRegex: /.{1,}/ + - id: $$cap_LND_LOOP_LISTEN_PORT + label: Lightning Node | Loop Listening Port + description: Port of the loop listener in the Lightning node. + defaultValue: 10009 + validRegex: /.{1,}/ + - id: $$cap_LND_BITCOIN_RPC_USER + label: Lightning Node | Bitcoin Node RPC User + description: Lightning node RPC user name which talks to the Bitcoin node. + defaultValue: lnd + validRegex: /.{1,}/ + - id: $$cap_LND_BITCOIN_RPC_PASSWORD + label: Lightning Node | Bitcoin Node RPC Password + description: Password of Lightning node RPC user that talks to the Bitcoin node. + defaultValue: afixedpasswordbecauselndsuckswithcookiefile + validRegex: /.{1,}/ + - id: $$cap_LND_BITCOIN_RPC_HASHED_PASSWORD + label: Lightning Node | Bitcoin Node RPC Hashed Password + description: Hashed password of Lightning node RPC user that talks to the Bitcoin node. + defaultValue: d031f7567c5b02ba95524170e51c77f4$827ce5412f653d6613c2f480e521eb437c866b999bdeb2ee4f9c41d3b00dff1c + validRegex: /.{1,}/ + - id: $$cap_LND_ADMIN_MACAROON_PATH + label: Lightning Node | Administrator Macaroon Path + description: Path to administrator macaroon file in the Lightning node. + defaultValue: /data/admin.macaroon + validRegex: /.{1,}/ + - id: $$cap_LND_INVOICE_MACAROON_PATH + label: Lightning Node | Invoice Macaroon Path + description: Path to invoice macaroon file in the Lightning node. + defaultValue: /data/invoice.macaroon + validRegex: /.{1,}/ + - id: $$cap_LND_READ_ONLY_MACAROON_PATH + label: Lightning Node | Read-Only Macaroon Path + description: Path to read-only macaroon file in the Lightning node. + defaultValue: /data/readonly.macaroon + validRegex: /.{1,}/ + - id: $$cap_LND_NO_REST_TLS + label: Lightning Node | Disable TLS For REST API + description: Whether to disable TLS for REST API calls in the Lightning node. + defaultValue: 'true' + validRegex: /^(true|false)$/ + - id: $$cap_LND_WUMBO_CHANNELS + label: Lightning Node | Wumbo Channels + description: Whether to use Wumbo channels in the Lightning node. + defaultValue: 'true' + validRegex: /^(true|false)$/ + - id: $$cap_LND_AUTOPILOT_ACTIVE + label: Lightning Node | Autopilot + description: Whether to use Autopilot in the Lightning node to automatically open and manage channels with peers. + defaultValue: 'true' + validRegex: /^(true|false)$/ + - id: $$cap_LND_AUTOPILOT_MAXIMUM_CHANNELS + label: Lightning Node | Autopilot Maximum Channels + description: Maximum amount of channels managed by Autopilot in the Lightning node. Only used when Autopilot is enabled. + defaultValue: 5 + validRegex: /.{1,}/ + - id: $$cap_LND_AUTOPILOT_ALLOCATION + label: Lightning Node | Autopilot Allocation + description: Allocation rate for Autopilot in the Lightning node. For example `0` means 0%, `0.5` means 50% and `1` means 100%. Only used when Autopilot is enabled. + defaultValue: 0.6 + validRegex: /.{1,}/ + - id: $$cap_LND_ADDITIONAL_ARGUMENTS + label: Lightning Node | Additional Arguments + description: Additional Lightning node startup arguments. + - id: $$cap_THUB_NO_VERSION_CHECK + label: Lightning Node Manager | Disable Version Checking + description: Whether to skip version checking in the Lightning node manager. + defaultValue: 'true' + validRegex: /^(true|false)$/ + - id: $$cap_THUB_COOKIE_PATH + label: Lightning Node Manager | Cookie + description: Path to the cookie file in the Lightning node manager. + defaultValue: /data/.cookie + validRegex: /.{1,}/ + - id: $$cap_THUB_ACCOUNT_CONFIG_PATH + label: Lightning Node Manager | Account Configuration + description: Path to the account configuration file in the Lightning node manager. + defaultValue: /data/thubConfig.yaml + validRegex: /.{1,}/ + - id: $$cap_THUB_SSO_MACAROON_PATH + label: Lightning Node Manager | Single-Sign-On Macaroon + description: Path to the single-sign-on macaroon file in the Lightning node manager. + defaultValue: /etc/lnd + validRegex: /.{1,}/ + - id: $$cap_THUB_SSO_CERT_PATH + label: Lightning Node Manager | Single-Sign-On TLS Certificate + description: Path to the single-sign-on TLS certificate file in the Lightning node manager. + defaultValue: /etc/lnd/tls.cert + validRegex: /.{1,}/ + - id: $$cap_THUB_NO_CLIENT_ACCOUNTS + label: Lightning Node Manager | Disable Client Accounts + description: Whether to disable client accounts in the Lightning node manager. + defaultValue: 'true' + validRegex: /^(true|false)$/ + - id: $$cap_THUB_LOG_LEVEL + label: Lightning Node Manager | Log Level + description: Log severity in the Lightning node manager. + defaultValue: debug + validRegex: /.{1,}/ + - id: $$cap_THUB_LOGOUT_URL + label: Lightning Node Manager | Logout URL + description: Logout URL in the Lightning node manager. + defaultValue: /server/services/thunderhub/BTC + validRegex: /.{1,}/ diff --git a/public/v4/logos/btcpayserver.png b/public/v4/logos/btcpayserver.png new file mode 100644 index 0000000000000000000000000000000000000000..ef56fe2faec1f011b21508e60c298f10acdd1200 GIT binary patch literal 13736 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