Install
Install on cPanel
Outcome: Mailnib running on your cPanel hosting, ready for the web installer.
This path uses the prebuilt application in the runtime/ folder of your download. Nothing is built or installed on the host: you upload, set two variables, and start.
Before you start
- Your cPanel has Setup Node.js App (sometimes listed under Software). If it does not, ask your host to enable Node.js hosting, or use Render.
- You can create a PostgreSQL database. Look for PostgreSQL Databases in cPanel. If your plan only has MySQL, create a free database on a hosted PostgreSQL service instead; MySQL will not work.
- The server is Linux x64 (almost every cPanel host is). The bundle contains native parts built for that platform.
1. Create the database
- In cPanel, open PostgreSQL Databases.
- Under Create New Database, enter a name such as
mailbuilderand click Create Database. - Under Add New User, create a user with a long password. Save the password somewhere safe.
- Under Add User To Database, choose the user and the database, click Add, and tick All privileges.
cPanel usually prefixes both names with your account name, for example acme_mailbuilder. Write down the full names you see on the page.
Your connection string has this shape:
postgresql://USER:PASSWORD@localhost:5432/DATABASE
If the password contains @, :, / or #, replace each with its percent-encoded form (@ becomes %40), or pick a password without them.
2. Upload the files
- Open File Manager and create an empty folder outside
public_html, for examplemailbuilder. - Upload your download ZIP into it, select the file and click Extract. You get a folder named
mailnibholdingruntime,source,documentationand some files. - Open
mailnib/runtime. You should seeapp.js,.env.exampleand a folder namedapps. This folder is the application. (You may deletesourceanddocumentationfrom the server to save space; keep your own copy of the download.)
3. Create the .env file
- In File Manager, inside
runtime, copy.env.exampleand name the copy.env. (Turn on Show Hidden Files in Settings if you cannot see it.) - Edit
.envand set these two lines:
DATABASE_URL=postgresql://acme_mailuser:YOUR-PASSWORD@localhost:5432/acme_mailbuilder
MIGRATE_ON_START=true
Leave
PUBLIC_APP_URL=empty: the installer asks for the address your customers will use and saves it. You can also set it here, starting withhttps://.Leave
APP_KEY=empty. The web installer then generates a strong key. At the end of the installer you may be shown the new key once, with a note that the configuration file could not be written: copy it into theAPP_KEY=line of.envand restart the app. Keep a private copy; it encrypts the secrets you save in the console.Leave
MAIL_TRANSPORT=empty. The platform then sends through the SMTP server you enter in the installer. Setting it tologstops all delivery.
Every other variable is explained in Configuration.
4. Create the Node.js app
- Open Setup Node.js App and click Create Application.
- Node.js version: 20 or newer.
- Application mode: Production.
- Application root: the
runtimefolder, for examplemailnib/mailnib/runtime. - Application URL: the domain or subdomain for the platform.
- Application startup file:
app.js. - Click Create.
Click Start App (or Restart if it is already running).
5. Check it is running
Open https://your-domain/api/health in a browser. You should see:
{"ok":true,"db":"connected","migrations":"up to date"}
The first start applies the database migrations, so it can take a minute. If you see something else, go to Troubleshooting.
6. Run the installer
- In File Manager, open
storage/.install/setup-tokeninside the application folder and copy the code. It is also printed in the application log (the log file is named on the Setup Node.js App page, oftenstderr.log). - Visit
https://your-domain/installand paste the token. - Follow the six steps in The web installer.
Changing settings after install
You never rebuild to change a setting. Every value is read when the app starts, so changing one takes a minute.
- Choose where to edit. Either works, and a value set in Setup Node.js App wins over the same line in
.env.- Setup Node.js App: open the application, scroll to Environment variables, click Add Variable (or edit the row), enter the name and value, and click Save.
.env: in File Manager, open.envinside theruntimefolder, edit the line, and save.
- Click Restart on the Setup Node.js App page. A restart is what applies the change.
- Reload the page that should change. For example, open
/robots.txtafter changingPUBLIC_APP_URL.
The variables you can set are listed, with what each does, in Configuration. The common ones are:
| Variable | Use it to |
|---|---|
DATABASE_URL | Point at a different PostgreSQL database. |
PUBLIC_APP_URL | Change the address in links, the sitemap and emails. |
SAMPLE_IMAGES_URL | Host the template sample photos yourself, or off for drawn placeholders. |
DEMO_MODE | Turn the public demo on (true) or off. |
MIGRATE_ON_START | Apply database updates on the next start. |
STORAGE_* | Move uploads to S3-compatible storage. |
Failed-payment reminders
If you take card payments, add a cPanel Cron Job that calls the reminder endpoint, as described in Payment providers. Set CRON_SECRET in .env, restart the app, and use the curl command from that page.
Keep your uploads safe
Customer images are saved in the storage/ folder of the application. Include that folder in your backups along with the database, or move uploads to S3-compatible storage with the STORAGE_* variables. See Updating and backups.
PostgreSQL role privileges
Use a dedicated login role that owns this application's tables and functions. It needs CONNECT and CREATE on the database, USAGE and CREATE on the application schema (public), and permission to create the drizzle migration schema. Migrations need to create and alter tables, indexes, policies, triggers and functions; normal operation reads and writes those tables and executes the shipped functions. Use the same role for the installer, migrations and DATABASE_URL.
NOSUPERUSER NOBYPASSRLS is supported and recommended. Neither superuser nor BYPASSRLS nor permission to create roles is required. Tenant tables retain FORCE ROW LEVEL SECURITY even for their owner. Verified webhooks, the authenticated operator console and the secret-authenticated dunning scheduler discover workspaces through fixed, read-only functions, then enter a workspace scope for tenant data and writes. Never share the application's database credentials with tenants or browser code. Test setup creates roles to verify isolation; those privileges are needed only by the test administrator.
On managed PostgreSQL, use the database/schema owner supplied by the provider, or have the provider grant the schema creation privileges above. On cPanel, ask the host to grant these privileges if the control-panel database user cannot create schemas or functions. No elevated RLS-bypass role is needed.