How to Install BillionMail on Hostinger VPS: Complete Setup Guide and Troubleshooting

Step-by-step guide to install BillionMail on a Hostinger VPS with Docker, plus real fixes for PostgreSQL migration errors, access denied, Coolify port conflicts and firewall issues.
BillionMail installation and troubleshooting on Hostinger VPS

To install BillionMail on Hostinger VPS, you need a VPS running Ubuntu with Docker, the official BillionMail installer, and a few open ports for the admin panel and mail services. The install itself takes minutes. Most of the time goes on what comes after: finding the right login URL, opening the right ports, sorting out conflicts with tools like Coolify, and fixing database migration errors if your version has them.

We recently set up BillionMail on a Hostinger VPS for a self-hosted email marketing server and ran into several problems that the standard instructions do not cover. This guide walks through the full setup and every fix we used, in the order you are likely to need them.

Key takeaways
  • BillionMail is a free, self-hosted mail server and email marketing platform that runs in Docker containers.
  • Get your login details with bash bm.sh default. Use the full URL it prints, including the SafePath, or you will see “access denied”.
  • If you already run Coolify or Traefik, keep BillionMail off ports 80 and 443 and check port usage before you install.
  • The PostgreSQL error column “1” does not exist is a query builder issue in some versions, fixed with gdb.Raw("1").
  • Never delete bm_relay_old or change source code without a database and file backup first.
  • A working dashboard does not mean email delivery works. Set up SPF, DKIM, DMARC, MX and reverse DNS, then test.

What is BillionMail?

BillionMail is an open-source mail server and email marketing platform that you host on your own server. It bundles everything needed to send and receive email and run campaigns: a web dashboard, contact lists, campaign sending, SMTP settings, domain management and delivery statistics, plus webmail for mailboxes.

Behind the dashboard, BillionMail runs as a set of Docker containers that work together:

Service What it does
Core application The dashboard, campaigns, contacts and settings
PostgreSQL Stores accounts, domains, contacts and campaign data
Redis Caching and queues
Postfix Sends and receives email (SMTP)
Dovecot Mailbox access over IMAP and POP3
Rspamd Spam filtering and DKIM signing
Webmail Browser-based mailbox access

The appeal is control and cost: no per-contact pricing and your data stays on your server. The trade-off is that you are responsible for the server, security and deliverability yourself.

Before you install BillionMail on Hostinger VPS

This is the environment we used. Yours may differ, so check your server before you start.

Component Our setup
Hosting Hostinger VPS
Operating system Ubuntu 24.04 LTS
Containers Docker with Docker Compose
Database PostgreSQL (installed by BillionMail)
Existing proxy Coolify with Traefik on ports 80 and 443
BillionMail admin ports 8888 (HTTP) and 8443 (HTTPS)

Before installing, check:

  • Resources: free RAM, CPU and disk space, especially if other apps already run on the VPS. Check the current minimum requirements in the official BillionMail repository.
  • A domain you can manage: you will need to add DNS records for sending.
  • Existing services and ports: anything already using ports 80, 443, 25 or the mail ports will conflict.
  • Outbound SMTP: some VPS providers restrict outbound traffic on port 25. Check Hostinger’s current policy for your plan before relying on the server for delivery.
  • A fresh snapshot: take a VPS snapshot or backup from the Hostinger panel so you can roll back.

Step 1: Check that Docker is installed

BillionMail runs everything in Docker. Connect to your VPS over SSH and check Docker and Docker Compose:

docker --version
docker compose version

Then see what is already running, so you know which containers and ports are in use:

docker ps

If Docker is missing, install it using Docker’s official instructions for Ubuntu, or choose a Hostinger VPS template that includes Docker.

Step 2: Install BillionMail

Use the installation method in the official BillionMail repository, because the maintainers update it. At the time of writing, the one-line installer clones the project into /opt/BillionMail and runs the install script:

cd /opt && git clone https://github.com/aaPanel/BillionMail && cd BillionMail && bash install.sh

When it finishes, check the project files and running containers:

cd /opt/BillionMail
ls -la
docker ps

You should see containers for the core application, PostgreSQL, Redis, Postfix, Dovecot, Rspamd and webmail. Read the installer output carefully: it lists the ports you need to open and may warn about conflicts.

Step 3: Find your login URL and password

Do not guess the login address or credentials. BillionMail has a command that prints them:

cd /opt/BillionMail
bash bm.sh default

The output looks similar to this:

BillionMail default info!

BillionMail Internet IPv4 Address:
https://YOUR_SERVER_IP:8443/billion

Username: billion
Password: billion

Open the full URL it prints, including the last part (the SafePath, /billion in this example). On our server the username and password were both billion, but yours may differ, so always use what the command shows. Change the admin password as soon as you log in.

Your browser will warn about the certificate on first visit because the panel uses a self-signed certificate on the IP address. That is expected until you put the panel behind a domain with a proper SSL certificate.

Step 4: Open the right ports on your Hostinger VPS

If the dashboard or mail services cannot be reached from outside, the firewall is the usual cause. Check both the Ubuntu firewall (if enabled) and the firewall rules in your Hostinger VPS panel. Depending on which services you use, the ports are:

Port Service
25 SMTP (server-to-server mail)
465 SMTP over SSL
587 SMTP submission
110 / 995 POP3 / POP3S
143 / 993 IMAP / IMAPS
8888 BillionMail admin (HTTP)
8443 BillionMail admin (HTTPS)

Open only what you actually use. Where possible, limit the admin ports to your own IP address rather than the whole internet. The same “smallest attack surface” rule we use in our WordPress security checklist applies to mail servers too.

Step 5: Set up your domain and DNS before sending

Once you can log in, add your sending domain in BillionMail. It will show the DNS records your setup needs. Typically these are:

  • A record for the mail hostname, pointing to your VPS IP.
  • MX record so other servers know where to deliver mail for your domain.
  • SPF to say which servers may send for your domain.
  • DKIM to sign your emails so receivers can verify them.
  • DMARC to tell receivers what to do with mail that fails SPF or DKIM.
  • PTR (reverse DNS) so your IP resolves back to your mail hostname. Set this in your Hostinger VPS panel or through support.

Use the exact values BillionMail and your DNS provider give you. Do not copy SPF, DKIM or MX values from another server or tutorial. Then send test emails to Gmail and Outlook accounts and check they land in the inbox before you send a real campaign.

Stuck on your BillionMail setup?

We set up and fix self-hosted servers, Docker apps and websites for clients in Pakistan, the USA, UK and worldwide. If your install is failing, the dashboard will not open or emails are not delivering, send us the error and we will tell you what is wrong.

Get help with your server →  or WhatsApp +92 315 3038021

BillionMail troubleshooting: problems we hit and how we fixed them

These are the real issues from our installation. Some only affect certain BillionMail versions, so check your own logs and code before applying any fix.

1. PostgreSQL error: column “1” does not exist

The core application logs showed:

Failed to cleanup duplicates or create unique index

ERROR: column "1" does not exist

The failing query was checking whether a database index already existed:

SELECT "1"
FROM "pg_indexes"
WHERE "indexname" = 'uk_relay_domain'
LIMIT 1;

Why it happens: the query builder wrapped 1 in double quotes. In PostgreSQL, double quotes mean “this is a column name”, so it looked for a column called 1, which does not exist.

The fix: in core/internal/service/database_initialization/smtp_relay.go, the code used:

Fields("1")

We changed it to GoFrame’s raw expression, so 1 is sent as a plain number:

exists, err := g.DB().Model("pg_indexes").Fields(gdb.Raw("1")).
    Where("indexname", "uk_relay_domain").
    Value()

This is a source-level workaround for the version we tested. Back up the original file, and check whether a newer BillionMail release already fixes it before you patch anything.

2. “Table bm_relay_old already exists”

The next startup message was:

Failed to rename old table bm_relay:
Table bm_relay_old already exists,
skipping rename operation

This means the migration tried to rename the old relay table, but a table with the target name was already there, usually left over from an earlier run. First, look at what exists:

SELECT tablename
FROM pg_tables
WHERE schemaname = 'public';

On our server the relevant tables were:

bm_relay_config
bm_relay_domain_mapping
bm_relay_old

We reviewed the migration condition in the source, adjusted it so it no longer tried to repeat the rename, then rebuilt and redeployed. After that the core container stayed running and the relay migration error no longer appeared in the logs.

Do not delete bm_relay_old just because the name says “old”. It may hold relay settings needed for migration or recovery. Take a database dump first and understand the migration logic before you change anything.

3. The build script fails on Ubuntu (apk: command not found)

To apply the source fixes we had to rebuild the core binary. The project’s build script failed because it calls apk, which is the package manager for Alpine Linux, not Ubuntu.

Instead of changing the server, we built inside a temporary Alpine Go container:

docker run --rm \
  -v /opt/BillionMail/core:/opt/core \
  -w /opt/core \
  golang:1.24-alpine \
  sh -c 'go mod download && GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o billionmail-amd64 main.go && ls -lh billionmail-amd64'

What each part does:

  • golang:1.24-alpine gives an Alpine environment with Go installed.
  • -v mounts the BillionMail source folder into the container.
  • GOOS=linux GOARCH=amd64 builds for a 64-bit Linux server.
  • --rm deletes the temporary container when the build finishes.

Use the Go version the project requires (check go.mod). Keep a copy of the original Docker image before replacing it with your custom build, so you can switch back.

4. Login page shows “access denied”

This almost always means the wrong URL or wrong credentials. Opening the server IP, or adding /login yourself, skips the SafePath that BillionMail uses to hide the admin panel. Run bash bm.sh default again and copy the exact URL and credentials it prints.

5. The dashboard will not open

Check the core container first:

docker inspect billionmail-core-billionmail-1 \
  --format 'Status={{.State.Status}} RestartCount={{.RestartCount}}'

You want Status=running and a restart count that is not climbing. Then check that the panel responds locally:

curl -sS -o /dev/null -w 'HTTP Status: %{http_code}\n' http://127.0.0.1:8888/

A 200 means the app is working and the problem is the firewall, ports or the URL you are using. If the container keeps restarting, read the logs:

docker logs --tail 100 billionmail-core-billionmail-1

Look for database connection errors, migration failures like the two above, or configuration problems. Container names can differ between versions, so confirm yours with docker ps.

6. Port conflicts with Coolify and Traefik

If Coolify already runs on your VPS, its Traefik proxy normally holds ports 80 and 443. Two services cannot share the same host port. Check what is listening before you change anything:

ss -tulpn
docker ps

We kept BillionMail’s admin panel on 8888 and 8443, which avoided the conflict. If you want the panel on a domain with a proper SSL certificate, route it through Traefik as a reverse proxy rather than changing Coolify’s port mappings, which can take your other apps offline.

7. Fail2ban: “Could not find server”

The core logs also showed:

fail2ban: ERROR Could not find server

This came from the Fail2ban security service, not the database, and did not stop the dashboard working. A warning from one supporting service does not mean all of BillionMail is down. Confirm the core app separately:

docker inspect billionmail-core-billionmail-1 --format '{{.State.Status}}'
curl -I http://127.0.0.1:8888/

Do not ignore repeated Fail2ban errors forever, because Fail2ban is what blocks password-guessing attacks. Investigate it as its own issue, and do not make database changes to fix it.

How to check BillionMail is running correctly

After any fix, run the same health check:

# All containers up?
docker ps

# Core app running and not restarting?
docker inspect billionmail-core-billionmail-1 \
  --format 'Status={{.State.Status}} RestartCount={{.RestartCount}}'

# Panel responding locally?
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8888/

# Any new errors?
docker logs --tail 100 billionmail-core-billionmail-1

On our server, after the fixes, the core container was running with a restart count of zero and the panel returned 200. Remember what this proves and what it does not: the application is working, but outbound delivery, DNS authentication and mailbox access still need their own tests.

Back up before you troubleshoot

Before changing source code, database tables or Docker images, make a recovery point:

  • PostgreSQL: take a database dump with pg_dump from inside the database container.
  • Configuration: copy .env, docker-compose.yml, mail and SSL configuration and the data folders.
  • Docker image: tag the original core image before you replace it with a custom build.
  • The whole VPS: take a snapshot in the Hostinger panel.

Keeping the server and its software updated matters as much as backups. Our article on the PHP2Shell vulnerability shows how quickly unpatched server software becomes a target, and our guide on what to do if your site is hacked explains why tested, off-server backups are the difference between a bad day and a disaster.

Should you self-host your email marketing?

Self-hosting with BillionMail makes sense if you send at volume, want to own your data and are comfortable managing a Linux server. It is a poor fit if nobody on your team can maintain the server, because deliverability, security updates and blacklist monitoring become your job. A new IP address also needs to build a sending reputation, so start with small volumes to engaged contacts and grow gradually.

If your emails are mainly order confirmations and contact form notifications from a WordPress or WooCommerce site, a reliable transactional SMTP service is often simpler. We set these up as part of our WordPress website development and WooCommerce development work.

Frequently Asked Questions

Can I install BillionMail on a Hostinger VPS?

Yes. BillionMail runs in Docker, so you can install it on a Hostinger VPS running a supported Linux system such as Ubuntu 24.04. Check the current requirements in the official BillionMail repository and make sure no other service already uses the ports BillionMail needs.

What is the default BillionMail login URL?

Run bash bm.sh default inside /opt/BillionMail. It prints the full login URL for your server, including the SafePath, for example https://YOUR_SERVER_IP:8443/billion. Opening the bare IP address or /login usually will not take you to the right page.

What is the default BillionMail username and password?

The bash bm.sh default command shows the credentials for your installation. On the server in this guide they were billion and billion, but yours may differ. Change the password straight after your first login.

Why does BillionMail show “access denied”?

Usually because the login URL is missing the SafePath or the username and password are wrong. Run bash bm.sh default to see the exact URL and credentials for your server, then log in using that full URL.

Why does PostgreSQL show “column 1 does not exist” in BillionMail?

In the version we tested, the query builder wrapped 1 in quotes, so PostgreSQL treated it as a column name instead of a number. Changing Fields(“1”) to Fields(gdb.Raw(“1”)) in smtp_relay.go fixed it. Check whether your release still has this code before changing anything.

Can BillionMail run alongside Coolify on the same VPS?

Yes, as long as the two do not fight over the same host ports. Coolify’s Traefik proxy normally uses ports 80 and 443, so keep BillionMail’s admin panel on its own ports such as 8888 and 8443, or route it through Traefik with a proper reverse proxy setup.

Is BillionMail ready to send emails straight after installation?

No. The dashboard working only proves the application is running. You still need to add your sending domain, publish SPF, DKIM, DMARC and MX records, set reverse DNS (PTR), confirm your VPS allows outbound SMTP and send test emails before running any campaign.

Need help with BillionMail or your server?

Codixity builds websites and sets up the servers behind them for clients in Pakistan, the USA, UK and worldwide, with 350+ projects over 6+ years. We can install BillionMail on your Hostinger VPS, fix errors like the ones above, configure DNS for delivery and keep everything updated. See our custom web app development service, or contact us directly:

Contact Codixity for a fixed quote →

Note: this guide documents a real installation on a specific BillionMail version and VPS setup. Application versions and installer behaviour change, so check the official BillionMail documentation and back up your system before applying any source code change.

Share this article
IB
Written by Izaan Bin Haider

Founder of Codixity. 6+ years and 350+ websites for small businesses in the USA, UK, Canada, Australia and beyond. Builds custom WordPress websites and web apps that bring in calls, not just compliments.

On this page

Free website review
Is your website costing you jobs?

Get the 3 biggest fixes for your site in 24 hours. Free, no obligation.

Get my free review →
Work with Codixity

Want a website that brings in calls, not just visitors?

Custom WordPress websites from $450, with fixed quotes and a reply within 24 hours.

Get a free quote →

Keep reading