Skip to content

Installation

This page describes the production installation flow for the Bangi Tracker application. Use this guide as a baseline, and update commands, versions, domains, and file paths to match your server and deployment setup.

1. Buy and Prepare a VPS

  1. Create a new VPS (Ubuntu LTS recommended).
  2. Choose server size, region, and authentication method (SSH key recommended).
  3. Connect to the server:
ssh root@<server-ip>
  1. Perform initial server hardening (for example, create a non-root user and configure a firewall). This is out of scope for this guide.

2. Configure Domain DNS

Point your domain to the VPS IP address.

  1. Open your DNS provider panel.
  2. Create or update an A record:
  3. Host: @ for the root domain, or a subdomain (for example, tracker for tracker.<your-domain>)
  4. Value: <server-ip> (your server's public IP address)
  5. TTL: <ttl-value> (DNS cache duration in seconds)
  6. Wait for DNS propagation.

DNS propagation often completes within a few minutes, but it can take up to 24-48 hours depending on your DNS provider, resolver caches, and TTL settings.

3. Set Up Let's Encrypt Certificate (Certbot)

HTTPS is required for production because it encrypts traffic between users and your server, protects credentials from interception, and improves user trust. Modern browsers also mark non-HTTPS sites as "Not secure", and some integrations require HTTPS to work correctly.

Install Certbot and request an SSL certificate for your domain.

sudo apt update
sudo apt install -y certbot python3-certbot-nginx
sudo certbot certonly --nginx -d <your-domain>

Let's Encrypt validates domain ownership before issuing a certificate. Many hosting providers (for example, DigitalOcean or Vultr) include nginx by default, so the --nginx challenge is usually the simplest option.

If nginx is not available in your environment, use Certbot standalone mode or a DNS challenge to validate domain ownership.

Verify auto-renewal:

sudo certbot renew --dry-run

Certificate paths:

  • /etc/letsencrypt/live/<your-domain>/fullchain.pem
  • /etc/letsencrypt/live/<your-domain>/privkey.pem

4. Start Application with Docker Compose

The application can be deployed to different environments. This tutorial describes how to deploy and start Bangi Tracker services using Docker Compose.

4.1 Install Docker and Docker Compose

Install required OS packages for adding external repositories:

sudo apt update
sudo apt install -y ca-certificates curl gnupg

Add Docker's official GPG key and APT repository:

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Install Docker Engine and Docker Compose plugin from the Docker repository:

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Start Docker on boot and verify Docker Compose is available:

sudo systemctl enable --now docker
docker compose version

4.2 Configure services

In this section, you will prepare all runtime configuration files for the stack: database credentials, backend environment variables, frontend API settings, and the IP2Location database file used by the backend.

Create a directory for Bangi Tracker.

mkdir -p /app/bangi-tracker
cd /app/bangi-tracker

Create local configuration files for the next steps:

touch bangi-db.env bangi-backend-config.env bangi-ui-config.js docker-compose.yml

Generate strong passwords before editing environment files:

openssl rand -base64 24

4.2.1 Configure MariaDB service

Edit bangi-db.env with the following configuration:

MARIADB_DATABASE=bangi_tracker
MARIADB_USER=bangi
MARIADB_PASSWORD=<generate-strong-password>
MARIADB_ROOT_PASSWORD=<generate-strong-password>

MariaDB configuration reference:

Must be changed for production security: - MARIADB_PASSWORD: Password for MARIADB_USER. - MARIADB_ROOT_PASSWORD: Root password for MariaDB container initialization and admin tasks.

Can be changed: - MARIADB_DATABASE: Database name for Bangi Tracker application data. - MARIADB_USER: Application database user (non-root).

4.2.2 Configure backend service

Edit bangi-backend-config.env with the following template:

MARIADB_HOST=mariadb
MARIADB_PORT=3306
BASIC_AUTHENTICATION_USERNAME=admin
BASIC_AUTHENTICATION_PASSWORD=<generate-strong-password>
LANDING_PAGES_BASE_PATH=/app/landings
IP2LOCATION_DB_PATH=/app/IP2LOCATION-LITE-DB1.IPV6.BIN
LANDING_PAGE_RENDERER_BASE_URL=http://landing-renderer/landings
INTERNAL_PROCESS_BASE_URL=http://localhost:8000/process

Environment variables reference:

Important:

  • Variables in this section are used by both application code and docker-compose.yml.
  • If you change service names, paths, URLs, or ports here, make matching updates in docker-compose.yml (for example, volumes, service references, etc.).

Must be changed for production security:

  • BASIC_AUTHENTICATION_PASSWORD: Password for authentication in Bangi Tracker.

Can be changed:

  • BASIC_AUTHENTICATION_USERNAME: Username for authentication in Bangi Tracker.

Should generally not be changed unless you also update docker-compose.yml (and understand the required related changes):

  • LANDING_PAGES_BASE_PATH: Filesystem path where landing page files are stored.
  • IP2LOCATION_DB_PATH: Filesystem path to the IP2Location database file.
  • LANDING_PAGE_RENDERER_BASE_URL: Base URL of landing renderer service used by backend for landing rendering.
  • INTERNAL_PROCESS_BASE_URL: Base URL for internal process endpoint used for domain/campaign processing.

4.2.3 Configure frontend service

Edit bangi-ui-config.js with the following configuration:

window.APP_CONFIG = window.APP_CONFIG || {
  BACKEND_API_BASE_URL: "https://<your-domain>/api/v2"
};

Frontend configuration reference:

  • BACKEND_API_BASE_URL: Public base URL used by UI for all backend API requests.

4.2.4 Configure IP2Location database

IP2LOCATION_DB_PATH points to the IP geolocation database file used by the backend. IP2Location provides multiple database variants; this setup has been tested only with IP2LOCATION-LITE-DB1.IPV6.BIN.

Setup steps:

  1. Register an account on the IP2Location website.
  2. Download the required IP2Location database file version for your deployment.
  3. Place the file in /app/bangi-tracker.

Maintenance:

IP2Location databases are updated periodically by the provider. Download new versions and replace the old file as part of routine maintenance.

Upload the IP2Location database from your local machine to the server with scp:

scp ~/Downloads/IP2LOCATION-LITE-DB1/IP2LOCATION-LITE-DB1.IPV6.BIN root@<server-ip>:/tmp

Then move the database file to the application directory:

mv /tmp/IP2LOCATION-LITE-DB1.IPV6.BIN /app/bangi-tracker/

4.3 Docker Compose setup

docker-compose.yml should contain:

services:
  mariadb:
    image: mariadb:11.4
    restart: always
    env_file:
      - bangi-db.env
    volumes:
      - .mariadb:/var/lib/mysql
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
  landing-renderer:
    image: php:8.2-apache
    volumes:
      - ./landings:/var/www/html/landings
  backend:
    image: ghcr.io/devalentino/bangi-backend:0.0.1a1
    restart: always
    env_file:
      - bangi-backend-config.env
      - bangi-db.env
    ports:
      - '8000:5000'
    volumes:
      - ./landings:/app/landings
      - ./IP2LOCATION-LITE-DB1.IPV6.BIN:/app/IP2LOCATION-LITE-DB1.IPV6.BIN
    healthcheck:
      test: [ "CMD", "curl", "-f", "http://0.0.0.0:5000/api/v2/health" ]
      interval: 120s
      timeout: 10s
      retries: 3
      start_period: 120s
    depends_on:
      mariadb:
        condition: service_healthy
  ui:
    image: ghcr.io/devalentino/bangi-ui:0.0.1a1
    restart: always
    ports:
      - '8001:80'
    volumes:
      - ./bangi-ui-config.js:/usr/share/nginx/html/app-config.js

Verify that all files were created:

ls -la

The output should look similar to:

total 11152
drwxr-xr-x 2 root root     4096 Feb 18 17:12 .
drwxr-xr-x 3 root root     4096 Feb 18 16:19 ..
-rwxr-xr-x 1 root root 11399090 Feb 18 17:06 IP2LOCATION-LITE-DB1.IPV6.BIN
-rw-r--r-- 1 root root      482 Feb 18 16:52 bangi-backend-config.env
-rw-r--r-- 1 root root      120 Feb 18 16:52 bangi-db.env
-rw-r--r-- 1 root root      111 Feb 18 16:53 bangi-ui-config.js
-rw-r--r-- 1 root root     1272 Feb 18 17:12 docker-compose.yml

Start the application:

docker compose pull
docker compose up -d

Check logs and container health:

docker compose ps
docker compose logs -f

5. Configure Nginx (SSL + Reverse Proxy)

Nginx is the final layer that ties together the domain, SSL certificates, and application services. It can also be used to configure additional campaign domains. Many hosting providers already include Nginx, which you can verify with:

sudo ls -la /etc/nginx/

If this directory exists and contains configuration files, you can skip the next installation step. If it does not exist, install Nginx.

5.1 Install Nginx (Ubuntu)

sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx
sudo nginx -v

5.2 Configure Nginx for your domain

Create a site configuration file at /etc/nginx/sites-available/<your-domain> with the following content:

server {
    listen 80;
    server_name <your-domain>;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name <your-domain>;

    ssl_certificate /etc/letsencrypt/live/<your-domain>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<your-domain>/privkey.pem;

    location /api/v2 {
        proxy_pass http://127.0.0.1:8000/api/v2;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location / {
        proxy_pass http://127.0.0.1:8001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

What this configuration does:

  • The first server block listens on port 80 (HTTP) and permanently redirects all traffic to HTTPS, so every request is secured.
  • The second server block handles encrypted traffic on port 443 using your Let's Encrypt certificate and private key. Certificates are generated in Section 3.
  • location /api/v2 proxies API requests to the backend container on 127.0.0.1:8000, preserving the /api/v2 prefix.
  • location / proxies all other requests to the frontend container on 127.0.0.1:8001.
  • The proxy_set_header directives forward the original host, client IP, and protocol so backend/frontend services can log real client information and correctly handle secure requests.

5.3 Enable and validate configuration

sudo rm -f /etc/nginx/sites-enabled/default
sudo ln -sf /etc/nginx/sites-available/<your-domain> /etc/nginx/sites-enabled/<your-domain>
sudo nginx -t
sudo systemctl reload nginx

What these commands do:

  • rm -f /etc/nginx/sites-enabled/default removes the default site to avoid conflicts with your domain-specific configuration.
  • ln -sf enables your site by creating (or replacing) a symbolic link from sites-available to sites-enabled, which is where Nginx loads active virtual hosts.
  • nginx -t validates the full Nginx configuration syntax and checks that referenced files (including certificates) are accessible.
  • systemctl reload nginx applies the new configuration without a full service restart, so existing connections are not interrupted.

5.4 Post-deploy verification (optional)

Run these checks after reloading Nginx:

curl -I http://<your-domain>
curl -I https://<your-domain>
curl -sS https://<your-domain>/api/v2/health
docker compose ps

Expected results:

  • http:// responds with 301 redirect to https://.
  • https:// responds with 200 and a valid TLS certificate chain.
  • /api/v2/health returns a healthy status payload.
  • docker compose ps shows backend, ui, and mariadb containers as running/healthy.

6. Application Sign In

After the deployment is complete, open your browser and navigate to:

  • https://<your-domain>

Sign in using credentials from backend environment variables:

  • Username: value of BASIC_AUTHENTICATION_USERNAME
  • Password: value of BASIC_AUTHENTICATION_PASSWORD