Installing "Dashboard for Paddle"

The simplest way to host Dashboard for Paddle is to use a small VPS instance, install Postgres and Caddy and run the Express app all on one box. This script was last tested on a Hetzner (CX22) Ubuntu 20.04 in October 2024, but should run on any base installation of a similar kind.

Overview

The steps required are simple:

  1. Create a new CX22 VPS at Hetzner and point a subdomain to it's IP.
  2. Install the latest version of node, postgres, cron, caddy, pm2 and the github client.
  3. Create a Postgres user and database.
  4. Configure the dashboard, build and let the first sync run.
  5. Let Caddy take care of reverse proxying to the express app.
  6. Configure the sync to run hourly.

Step 1: Install nvm and node

Install NVM to get latest node

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash

When finished, load NVM into PATH with these commands, to enable nvm to run

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

Now install the most current version of node

nvm install node

Step 2: Install other packages

Install Postgres, Cron and NPM

sudo apt update && sudo apt upgrade && sudo apt install postgresql cron npm

Install Caddy from their source (with key)

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

Install the GitHub Client (option, you can also use only Git if you prefer)

(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
 && sudo mkdir -p -m 755 /etc/apt/keyrings \
 && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
 && sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
 && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
 && sudo apt update \
 && sudo apt install gh -y

Step 3: Clone the repository

Use GitHub client to login.

gh auth login

When prompted, select github.com, HTTPS and the browser login.

Note: Opening the browser will fail if you are in a terminal session. Simply open the verification link provided in a local browser, copy-and-paste the code and authenticate the session.

Now clone the dashboard-for-paddle repository

mkdir /var/www
cd /var/www
gh repo clone boathouseco/dashboard-for-paddle

Now create a database user called portal (with identical password). By default, PostgreSQL accepts connections only from the localhost. If you ever allow remote connections change the password to a stronger one and change the .env file created below.

sudo -u postgres createuser portal

Next create a database and give that new user full rights

sudo -u postgres createdb dashboard-for-paddle
sudo -u postgres psql -c "ALTER USER portal WITH ENCRYPTED PASSWORD 'portal'"
sudo -u postgres psql -c 'GRANT ALL PRIVILEGES ON DATABASE "dashboard-for-paddle" TO portal;'
sudo -u postgres psql -d dashboard-for-paddle -c 'GRANT ALL PRIVILEGES ON SCHEMA public TO portal;'

Step 4: Setup environment

Switch to the repo directory and create the environment file.

Note: Change the PADDLE_KEY to your Paddle API Key and PADDLE_ENV to either sandbox or production depending on what environment your API Key is for.

cd /var/www/dashboard-for-paddle
echo "DASHBOARD_USER=demo" >> .env
echo "DASHBOARD_PASS=demo" >> .env
echo "PADDLE_KEY=CHANGEME" >> .env
echo "PADDLE_ENV=sandbox" >> .env
echo "DB_CONNECTION_STRING=postgresql://portal:portal@localhost/dashboard-for-paddle" >> .env

Step 5: Build and First Sync

Install all dependencies and build the project.

npm install
npm run build
npm run prisma:seed

If all steps succeed you can run the first sync which may take a while depending on how much data you have. You can continue with the remainder of the setup The import event log entry will indicate the current event number and estimated total number of events in your account.

Note: The estimated total shown when the job runs is returned from the Paddle API and in our experience at time of writing is not exact. You most likely will see log output indicating is importing an event number that far exceeds the estimated total (in one of our tests 400K events were estimated at 250K) We include it anyway in hope that the API estimations improve in future.

If you have more than 10K subscriptions this task is likely to take 12+ hours as the dashboard fetches all the subscriptions to get next payment/recurring transaction data. The log will display this as "rectifying the subscription". There is unfortunately no batch method to get recurring transaction data from Paddle, so the job fetches each one seperately (sequentially not to run into rate limiting issues).

npm run job:sync

Step 6: Setup PM2

Install PM2 and add two jobs. The first process will run the node web service, the second will host the sync job.

sudo npm install pm2@latest -g
pm2 startup systemd
pm2 start npm --name "dashboard-for-paddle" -- run start
pm2 start npm --name "dashboard-for-paddle-sync" --no-autorestart -- run job:sync

Note: you can view the output of any process under PM2 management with pm2 monit

Step 7: Setup Caddy

Caddy will reverse proxy (and handle SSL) for a domain (or subdomain) of your choice to the node process (remember to map the domain/subdomain to the A-record of your server).

mkdir /etc/caddy
nano /etc/caddy/Caddyfile

This opens the Caddy configuration file. Copy-and-paste the following contents, but replace the domain with your own.

subdomain.yourdomain.com {
    reverse_proxy 0.0.0.0:3000
}

Then restart Caddy with the new configuration.

sudo systemctl daemon-reload
sudo systemctl enable --now caddy
sudo systemctl reload --now caddy

You should now be able to see your dashboard at the domain.

Step 8: Setup sync as cron job

Run this command to open the current cron configuration file.

crontab -e

Note: You may be asked to choose your editor. Nano is a good choice.

Add this line to the file to run the sync every hour (via PM2).

0 * * * * /usr/local/bin/pm2 start "dashboard-for-paddle-sync" > /var/www/dashboard-for-paddle/sync.log 2>&1

Step 9: Testing

The first time you open the portal in your web browser you might be greeted with an SSL error while Caddy generates the certificate for your subdomain. In general this resolves within 5 minutes depending on the status of the Let's Encrypt servers.