VeroSMS Docs
Installation Guide

Get VeroSMS running

Build your own copy of the Android app, put the panel on your hosting, pair a phone, and watch it send a real text. Follow the parts in order and nothing here assumes you have done any of it before.

Version 4.0.1 Laravel 12 PHP 8.2+ MySQL 5.7+ Android 7+
Start here

Introduction

VeroSMS is a self-hosted SMS gateway. Instead of buying messages from a bulk SMS provider, you pair your own Android phones with your own copy of the panel and send through the SIM cards already in them — one message, thousands of messages, or a personalised campaign, from the panel or from your own software over the API.

You install it once, on your own hosting, and you are the only person who uses it. There is one panel and one account. You can create extra staff logins with roles for the people who work with you, and that is as far as it goes.

This guide covers installation and first-run setup only. For day-to-day use of the panel — every screen and what it does — see the User Manual included in the same download.

You do not need to be a developer. Part 1 walks through Android Studio click by click, and Part 2 is a five-minute wizard in your browser. If you can upload a file and create a MySQL database in cPanel, you can finish this guide.

Do the Android app first, before you touch the server. The app has to exist before a phone can be paired, and the Firebase project you create in step 1 is also what the server needs later. Working in the other order means going back and redoing things.

Firebase is not optional. Without it the panel installs perfectly, accepts messages perfectly, and never delivers one. Messages sit at queued and no error appears anywhere — not on the screen, not in the logs. Both Firebase steps in this guide have to be done.

Start here

How VeroSMS works

Five minutes here saves an hour later, because almost every problem people hit is a break in one specific link of this chain.

The path of one message
Panel or API  →  your server  →  Firebase  →  the phone  →  the SIM  →  recipient
                     ↑                                          │
                     └─────────  what happened  ────────────────┘
  • The panel or the API accepts your send and writes each message into a queue, addressed to one specific phone and one specific SIM slot.
  • Your server then sends a Firebase push to that phone. This is the only thing that can wake a sleeping Android handset — nothing else is allowed to.
  • The phone wakes up, calls back for its own queued messages, and puts them on the network through the SIM you chose.
  • The phone reports back what happened — sent, delivered, failed — and the panel shows it against the message.
  • Replies that arrive on that SIM are caught by the app and appear in the panel's Inbox.

Nothing is lost when a link breaks. A phone that is switched off, out of coverage or not yet paired leaves its messages waiting in the queue, and they go out when it comes back. That is why a half-finished installation looks like silence rather than an error.

Start here

What is in the download

The file you downloaded from CodeCanyon unzips to this:

Download contents
VeroSMS Project Files/
├── admin-panel-source-code/
│   └── source-code.zip    The web application. This is what goes on your server.
├── Android App Source Code/           The Android Studio project. This is what you build
│                          your own app from, in Part 1.
├── documentation/
│   ├── index.html         This guide.
│   └── readme.txt         What each folder is, and where to get help.
└── user-manual/           How to use the panel, screen by screen.

Two folders matter and the rest are reading. Verosms App/ is Part 1 of this guide, source-code/ is Part 2.

Do not upload the whole download to your server. Only source-code.zip goes online. Putting the documentation, the user manual and the Android project on a public web server publishes files that serve no purpose there.

Start here

What you need

Gather these before you start. Almost every shared host sold in the last few years meets the server side, and the installer checks all of it for you and says exactly what is missing.

On your computer, for Part 1

  • A Google account — any Gmail address works. This is what you sign into Firebase with.
  • Android Studio — free, from Google. Step 4 tells you where to get it.
  • About 10 GB of free disk space and a reasonable connection. The first time Android Studio opens a project it downloads a lot.

Server

RequirementMinimumNotes
PHP8.28.3 or 8.4 recommended
MySQL5.7MariaDB 10.3+ also works
Web serverApache / Nginx / LiteSpeedmod_rewrite enabled on Apache
HTTPSRequired in productionAndroid refuses plain http by default
Outbound HTTPSMust be allowedYour server calls Firebase; a host that blocks it stops delivery
CronOnce per minuteStep 4 of Part 2
Disk~250 MBPlus room for logs and uploads

PHP extensions

All of these are required. Most are switched on by default, and the installer tells you if one is not:

ExtensionExtensionExtensionExtension
BCMathCtypecURLDOM
FileinfoJSONMbstringOpenSSL
PDOPDO MySQLSessionTokenizer
XMLGDZip

Writable folders

These three must be writable by the web server. On cPanel set them to 755; if the installer still reports them as unwritable, use 775.

Must be writable
storage/
bootstrap/cache/
public/uploads/

Phones

RequirementMinimumNotes
Android7.0 (API 24)Android 9 or newer recommended
Google Play servicesRequiredFirebase push does not work without it
SIM1 or 2 slotsDual-SIM handsets work, each slot separately
An SMS allowanceYesEvery message is a real SMS, charged by your carrier
Part 1 — step 1

Create a Firebase project

Firebase is a free Google service. VeroSMS uses one small part of it: the ability to wake a phone that is asleep. A phone cannot be reached over the internet on demand — it sleeps, its address changes, and Android will not let an app sit awake waiting. A Firebase push is the knock on the door.

Everything else in Part 1 depends on this project existing, so it comes first.

1

Open the Firebase console

In your browser, go to the address below and sign in with your Google account.

Open in your browser
https://console.firebase.google.com
2

Click Create a project

It is the big card with a plus sign on it. On an account that already has projects, the same button reads Add project.

3

Give it a name

Anything you like — your company name, or just VeroSMS. Nobody but you sees it. Google adds a few random characters to make the internal id unique; that is normal and you can ignore it. Click Continue.

4

Switch Google Analytics off

The next screen offers Google Analytics. VeroSMS does not use it. Turn the toggle off and click Create project. Leaving it on does no harm, but it adds two more screens you do not need.

5

Wait for it, then click Continue

A spinner runs for twenty or thirty seconds and then says Your new project is ready. Click Continue and you land on the project overview page, with your project name at the top left.

Leave this tab open. The next step starts from this page.

This is free. Firebase Cloud Messaging costs nothing on the free Spark plan, no matter how many messages you send. No card, no per-message cost, nothing to cancel later. Google may show you an upgrade offer; you do not need it.

Part 1 — step 2

Register the Android app

Your Firebase project now exists, but it does not know about any app yet. Telling it about yours is what produces the file the app needs — and it is where you choose your package name.

First: what a package name is

A package name is the permanent, worldwide-unique id of an Android app. It is not the name people see on the phone; that is the app name, which you set separately in step 5. The package name is what Android, Google Play and Firebase use behind the scenes to tell your app apart from every other app in the world.

It is written in reverse-domain form — your domain backwards, then a word for the app:

The shape of a package name
com.yourcompany.yourapp

So if your website is acmetrading.com and you want to call the app Acme SMS, a good package name is com.acmetrading.acmesms. You do not have to own the domain, and nothing checks — it is a naming habit that keeps ids from colliding.

The rules

  • Lower case letters, digits and dots. Nothing else.
  • No spaces and no hyphens. com.acme-trading.sms is not valid; com.acmetrading.sms is.
  • At least two parts separated by a dot. Three is normal.
  • No part may start with a digit. com.4acme.sms is not valid.
  • Do not use com.example or anything with "example" in it. Google Play rejects it, and it marks the app as a leftover template.

Decide this now, and write it down. Firebase and Android Studio must be given exactly the same package name, character for character, and you are about to type it into Firebase. If they disagree, the app builds and installs quite happily and then never receives a single push — no error, no warning, just silence.

It also cannot be changed after an app is published: to Android, a different package name is a different app, not a new version of the same one. Pick something you will still be happy with in three years.

1

Click the Android icon

On the project overview page, in the middle, is a line reading Get started by adding Firebase to your app with a row of round icons under it. Click the Android one — the green robot head.

2

Type your package name

The first box is labelled Android package name and it is the only one that matters. Type the package name you decided on above. Check it twice.

3

Leave the other two boxes alone

App nickname is optional and only ever shown to you inside Firebase. Debug signing certificate SHA-1 is optional and not needed — it is for Google sign-in and similar features that VeroSMS does not use. Leave it empty.

4

Click Register app

After a few seconds the page moves on to a step called Download config file, with a download button on it. That is the next section of this guide — do not close the tab.

Keep your package name somewhere you can copy it from. A note on your desktop is fine. You will type it again in step 6, and it has to match this one exactly.

Part 1 — step 3

Download google-services.json

This small text file is how the app knows which Firebase project it belongs to. Without it in the right place, the app cannot be woken, and everything downstream of that fails quietly.

1

Click Download google-services.json

You are on the Download config file step from a moment ago. The button is in the middle of the screen. The file lands in your Downloads folder.

2

Move it somewhere you will find it again

Your desktop is ideal. You need it in step 7, possibly an hour from now, and hunting through Downloads for a file called google-services.json next to forty other things is a bad five minutes.

Do not rename it. Android Studio looks for that exact filename.

3

Click Next until you reach the console

Firebase now shows two screens of setup instructions about adding SDKs to your Gradle files. Skip them. The VeroSMS project already has every one of those lines in it. Click Next, then Next, then Continue to console.

If you lose the file, you can get it again. In the Firebase console, click the gear beside Project Overview, choose Project settings, scroll to Your apps, and there is a download button next to your Android app. It is the same file.

This is not the file your server needs. There are two different Firebase files in this guide and they are not interchangeable. This one belongs to the app. The other one — the service account key — is downloaded in Part 2, step 5 and belongs to the server. Do not swap them.

Part 1 — step 4

Open it in Android Studio

Android Studio is the free program Google makes for building Android apps. You will use perhaps five of its menus. It is large and it is slow the first time, and then it is fine.

1

Download and install Android Studio

Go to the address below, click the big download button, accept the terms, and install it the way you install anything else on your computer. It is free, and there are versions for Windows, macOS and Linux.

Open in your browser
https://developer.android.com/studio

The first time you run it, a setup wizard appears. Choose Standard and accept the licences. It then downloads the Android SDK, which is another large download. Let it finish.

2

Unzip the Android project from your download

From the CodeCanyon download, take the Verosms App/ folder and put it somewhere sensible on your computer — your Documents folder is fine. If it arrived as a zip inside that folder, extract it first.

Keep the path short and free of spaces and accented characters. Some Gradle versions still trip over them.

3

File › Open

In Android Studio, use the File menu and choose Open. On the welcome screen that appears when no project is open, the same thing is the Open button.

Navigate to the app folder and select the folder itself — not a file inside it, and not the folder above it. The right folder is the one that directly contains a folder called app and a file called settings.gradle. Android Studio marks it with a small green robot icon. Click OK.

If you are asked whether you trust the project, click Trust Project.

4

Wait for Gradle to finish

Gradle is the tool that assembles the app. On first open it downloads itself, plus the libraries the project uses. This takes ten to thirty minutes on a normal connection, and it only happens once.

While it runs, the bottom of the window shows a progress bar and text like Gradle: resolving dependencies. The editor may show red underlines everywhere. Ignore all of it and do not start clicking around.

You are done when the status bar at the bottom reads Gradle sync finished (some versions say Sync successful, or show a green tick in the Build panel). The red underlines disappear at that moment, and the left-hand Project panel fills with folders.

5

Say no to every upgrade it offers

Android Studio will pop up suggestions along the lines of Android Gradle Plugin upgrade recommended, Gradle update available or Plugin update available. Dismiss them. Click Don't remind me again for this project, or just close the notification.

The project is built and tested against the versions it ships with. Accepting an upgrade rewrites your build files and is the single most common way people turn a working project into a page of errors they cannot read.

If the sync fails, the Build panel at the bottom shows a red message. Nine times out of ten it is one of two things: no internet connection reaching Google's servers, or a company or school network blocking them. Check the connection, click Try Again, and see Troubleshooting if it persists.

Two panels are worth knowing. The Project panel down the left side is the file tree; everything this guide asks you to open is found there. The Build panel along the bottom is where Android Studio says whether the last thing worked.

Part 1 — step 5

Change the app name

This is the name that appears under the icon on the phone and in Android's app list. It is ordinary text: spaces, capitals and accents are all fine. It has nothing to do with the package name.

1

Open the file that holds it

In the Project panel on the left, open the folders one at a time until you reach this file, then double-click it:

File to open
app/src/main/res/values/strings.xml

A quicker route, once you trust it: press Shift twice, type strings.xml, and press Enter.

2

Find the app_name line

Near the top of the file is a line that looks like this. The text between the two tags is the name on the phone:

In strings.xml
<string name="app_name">VeroSMS</string>
3

Replace the text in the middle

Change only the words between > and <. Leave name="app_name" exactly as it is — that is the label Android looks the name up by, not the name itself.

After your edit
<string name="app_name">Acme SMS</string>
4

Save

Ctrl+S, or ⌘S on a Mac. Android Studio also saves on its own, but get into the habit.

Keep it short. Android gives you room for roughly twelve characters under an icon before it starts cutting the name off with a dash.

Do not touch the other lines in this file. They are text the app shows on its own screens. Changing one at random produces an app with an empty button on it, and the mistake is not obvious later.

Part 1 — step 6

Change the package name

This is the step where the app is told the id you registered in Firebase back in step 2. Get this exactly right and the rest of Part 1 is mechanical. Get it wrong by one character and the app installs and never receives anything.

There are two halves to it: two lines in a build file, which is the half that actually matters, and the folder names, which are cosmetic. Do them in that order.

1

Open the module build file

In the Project panel, open this file:

File to open
app/build.gradle

There are two files called build.gradle in the project. You want the one inside the app folder. In the Android view of the Project panel they are grouped under Gradle Scripts and the right one is labelled (Module :app). The other one, labelled (Project), is not it.

2

Find namespace and applicationId

Near the top, inside the android { } block, are two lines that both contain the package the app currently ships with:

In app/build.gradle
android {
    namespace = 'com.softnix.verosms'

    defaultConfig {
        applicationId "com.softnix.verosms"
        minSdk 24
        targetSdk 37
        ...
    }
}

The exact text in your copy may differ. Whatever is there, those two lines are the ones to change.

3

Put your own package name in both

Replace the text inside the quotes on both lines with the package name you registered in Firebase. Keep the quotes. Keep everything else on the line.

After your edit
android {
    namespace = 'com.acmetrading.acmesms'

    defaultConfig {
        applicationId "com.acmetrading.acmesms"
        minSdk 24
        targetSdk 37
        ...
    }
}

Do not change minSdk or targetSdk. minSdk 24 is what lets the app run on Android 7 and newer.

4

Click Sync Now

Saving the file makes a yellow bar appear across the top of the editor reading Gradle files have changed since last project sync. Click Sync Now on the right of that bar and wait for Gradle sync finished at the bottom.

applicationId is the one that must match Firebase, exactly. It is the id the built app carries, and it is the id Firebase checks a push against. com.acme.sms and com.acme.SMS are two different apps as far as Android is concerned.

Compare it against Firebase now, on screen, rather than from memory: Firebase console › gear icon › Project settingsYour apps. The package name is printed there. If the two differ, fix this file — not Firebase, because a registered package name cannot be edited afterwards.

The folders, if you want them to match

Your Java code still lives in folders named after the old package. Android does not care — the app builds and runs perfectly either way, because applicationId is what gets shipped. If tidy folders matter to you, Android Studio can rename them safely:

1

Show the parts separately

In the Project panel, open app › java. You see the old package as one long line, like com.softnix.verosms. Click the gear icon at the top of the Project panel and untick Compact Middle Packages. The single line becomes three nested folders: com, then softnix, then verosms.

2

Rename one folder at a time

Right-click a folder, choose Refactor › Rename. If a dialog asks, choose Rename package. Type the new name for that one part only — acmetrading, not the whole dotted string — and click Refactor.

Repeat for each part you are changing. Android Studio rewrites every reference in the code as it goes; that is exactly why you use this menu instead of renaming folders by hand.

3

Sync and rebuild

Click Sync Now if the yellow bar reappears, then Build › Clean Project, then Build › Rebuild Project. Watch the Build panel for BUILD SUCCESSFUL.

If the rename goes wrong, undo it and move on. Press Ctrl+Z / ⌘Z until the folders are back, or close the project without saving and reopen it. The folder names are decoration. As long as namespace and applicationId hold your package name and the project builds, your app is correct and nobody will ever see those folders.

Part 1 — step 7

Add your google-services.json

The project ships with a placeholder copy of this file so that it builds out of the box. It points at a Firebase project that is not yours. Replacing it is what ties the app to your project.

1

Find the file that is already there

The file sits directly inside the app folder:

Where it goes
app/google-services.json

The Project panel hides it in the default Android view. Click the dropdown at the top of that panel — it says Android — and change it to Project. You now see the real folders on disk, and google-services.json is inside app, next to build.gradle.

2

Delete it

Right-click the existing google-services.json and choose Delete. Confirm.

3

Drop yours in its place

Drag your downloaded google-services.json from your desktop onto the app folder in the Project panel. Android Studio asks where to put it and offers the path; accept it. Alternatively copy the file into the app folder in your computer's own file browser — it is the same thing.

Check the name has no (1) or -2 in it. A file called google-services (1).json is invisible to the build, and the app silently keeps using nothing.

4

Sync once more

Use File › Sync Project with Gradle Files. If the package name in your file does not match the applicationId you set in step 6, the build fails here with a clear message naming both. That is a useful failure, not a disaster: fix the applicationId to match and sync again.

Switch the Project panel back to Android when you are done if you prefer that view. Nothing depends on it; it only changes what you see.

Part 1 — step 8

Build the APK

An APK is the single file that installs an Android app. This step turns the project into one.

1

Build › Build Bundle(s) / APK(s) › Build APK(s)

Open the Build menu at the top, hover Build Bundle(s) / APK(s), and click Build APK(s). Do not pick Build Bundle(s) — a bundle is a Play Store upload format and cannot be installed on a phone.

2

Wait for it

The first build takes a few minutes; later ones take seconds. The Build panel at the bottom ends with BUILD SUCCESSFUL.

3

Click locate in the notification

A small notification appears in the bottom right: APK(s) generated successfully, with a locate link. Click it and your computer's file browser opens on the folder containing the file.

If the notification has already faded, the file is here, under your project folder:

Where the APK lands
app/build/outputs/apk/debug/app-debug.apk
4

Copy it somewhere sensible

Rename it to something you will recognise — acme-sms.apk — and keep it with your other project files. That one file is your app. Anyone you hand it to can install it.

A debug build is a real, fully working app. It sends real SMS, it receives pushes, it does everything. "Debug" only describes how it is signed. For your own phones it is all you ever need.

If you want a release build

A release build is signed with a key that is yours, which is required to publish on Google Play and sensible if you are distributing the app more widely. It lands in app/build/outputs/apk/release/ instead.

  • Use Build › Generate Signed Bundle / APK, choose APK, and click Next.
  • Click Create new… to make a keystore. Choose a path, set two passwords, fill in the name fields, and click OK.
  • Choose the release build variant and click Create.
  • Back up the keystore file and both passwords. They cannot be recovered or regenerated, and without them you can never publish an update to the same app on Google Play. Keep a copy somewhere that is not this computer.
Part 1 — step 9

Install it on a phone

Any handset on Android 7 or newer, with Google Play services and a SIM in it.

Read this before you start: Google Play Protect blocks this install on many phones.

It is not a fault in the app and it does not mean anything is wrong with your build. Google treats the permission to send SMS as highly sensitive, so Play Protect refuses to install any app that asks for it from outside the Play Store — including a signed build of your own. You may see Unsafe app blocked, App scan blocked this install, or an install that simply fails with no reason at all.

The fix is to turn Play Protect off, install, and turn it back on. On the phone: open the Play Store app › tap your profile picture, top right › Play Protect › the gear icon › turn off Scan apps with Play Protect › install the APK › turn the setting back on.

Once the app is installed it keeps working normally with Play Protect switched back on. You only need this during the install itself.

1

Get the APK onto the phone

Email it to yourself and open it on the phone, put it in Google Drive or Dropbox and download it there, or plug the phone into the computer with a USB cable and copy it to the Downloads folder. Any of these is fine.

2

Turn Play Protect off

As described in the warning above. Do it now, before you tap the file.

3

Tap the file and allow installs from that app

Open the phone's Files app, find the APK in Downloads, and tap it. Android says the app you are using is not allowed to install unknown apps. Tap Settings, switch Allow from this source on, and press Back. Tap the file again, then Install.

You are granting this to the app you opened the file with — Files, Chrome, Gmail. It is a one-off and only affects that app.

4

Turn Play Protect back on

Same path as before. Do it straight away, while you remember.

5

Open the app and grant its permissions

The app asks for several permissions as it starts. Grant all of them. It cannot work without them, and Android will not ask twice — a refusal has to be undone by hand in Settings.

PermissionWhy the app needs it
Send SMSThe entire point. Without it nothing sends.
Receive SMSReplies are captured and appear in the panel's Inbox.
Phone state & phone numbersTells the app which SIM sits in which slot, so you can pick one.
NotificationsAndroid requires a visible notification for a service that keeps running in the background. That small permanent notification is how the app stays alive.
6

Turn battery optimisation off for the app

In Android's Settings › Apps › your app › Battery, choose Unrestricted.

Skip this and Android puts the app to sleep after a while. Messages then arrive in bursts, hours late, usually the moment somebody unlocks the phone — which looks like a fault in the server and is not.

On Xiaomi, Oppo, Vivo, Realme and Huawei handsets there is a second setting of the manufacturer's own, usually called Autostart, App launch or Protected apps. It is not where Android puts its own setting, and it overrides it. Turn it on too.

The app has nothing to configure. No server address to type, no login. It stays on the pairing screen until Part 2 gives it a code. That is expected — leave it there and go and install the server.

Part 2 — step 1

Upload the files

Open the source-code/ folder from your download. Inside it is a single file, source-code.zip. That one file is the entire web application, and it is the only thing that goes on your server.

1

Choose where it goes

Main domain (example.com) — upload into public_html/.

Subdomain (sms.example.com) — create the subdomain in cPanel first, then upload into the folder it made.

Subfolder (example.com/sms) — upload into public_html/sms/.

2

Upload the zip and extract it

In cPanel File Manager, open the folder you chose, click Upload, and pick source-code.zip. When the upload finishes, go back to the folder, select the file, and click Extract.

It ships as a zip on purpose. Uploading thousands of loose files over FTP is slow and quietly drops a few on the way, and one missing file produces errors that look nothing like the real cause.

3

Check the structure, then delete the zip

After extracting you should see app/, public/, vendor/, artisan and the rest sitting directly in your chosen folder — not nested inside another folder.

If everything landed one level too deep, move the contents up. Then delete source-code.zip from the server: it is not needed any more, and leaving a downloadable copy of your whole application online is not something you want.

Point your domain at public/. Everything above public/ — including .env, which holds your database password, and the Firebase key you upload later — must not be reachable from a browser.

On cPanel, set the domain's Document Root to public_html/public. If your host does not allow that, the included .htaccess forwards requests correctly, but changing the document root is safer and faster.

Part 2 — step 2

Create a database

VeroSMS needs an empty MySQL database and a user with full access to it. Create both before running the installer.

1

Open MySQL Databases in cPanel

Create a database — call it verosms. cPanel prefixes it with your account name, giving something like myaccount_verosms. That full prefixed name is what the installer needs, not the short one you typed.

2

Create a database user

On the same screen, further down. Use the password generator, and paste the password into a note before you click Create. You will need it in a minute and cPanel will not show it to you again.

3

Add the user to the database

Further down again: pick the user, pick the database, click Add, then tick ALL PRIVILEGES and save.

This is the step people skip. The installer reports it as a connection failure rather than a permissions one, because from the outside the two look identical.

Write down four things: database name (with the prefix), database user (with the prefix), password, and host. The host is almost always localhost; a few hosts use a separate database server address, which they will have told you.

Part 2 — step 3

Run the installer

Open your domain in a browser. VeroSMS notices it has not been installed yet and sends you to the wizard on its own. If it does not, go straight to the address below.

Open in your browser
https://yourdomain.com/install
1

Welcome — /install

Says what the wizard is about to do. Click through.

2

Server requirements — /install/requirements

Every PHP version, extension and folder permission is checked and shown with a tick or a cross. You can only continue when everything passes.

If something fails, fix it and reload this page — you do not have to start the wizard again. Permission failures are the most common; see Troubleshooting.

3

Database details — /install/database

Enter the four things you wrote down in step 2. The installer tests the connection before writing anything, so a typo here costs you nothing but a retry.

4

Creating the tables — /install/database/migrate

This screen builds the database. On a shared host it takes anywhere from a few seconds to a minute. Do not close the tab or press Back while it runs.

5

Administrator account — /install/account

This is your own login for the panel. Use a real email address you can receive mail at: password resets go there.

6

Finished — /install/finish

Done. The installer locks itself so it cannot be run a second time, which also means nobody can reach that URL later and reinstall over your data.

You can sign in now at https://yourdomain.com/admin/login. Read First login before you do — on a seeded install there is a shipped password you must change.

Three things still stand between you and a delivered message: the scheduler, the Firebase service account key, and a paired phone. The next four sections are not optional. Skip any of them and the panel accepts messages and never sends one, without raising a single error.

Part 2 — step 4

Set up the scheduler

Background work runs on a timer: releasing scheduled campaigns when their time comes, retrying messages a phone never collected, marking phones offline when they stop reporting in, and clearing out expired pairing codes. All of it runs from one cron entry.

1

Open Cron Jobs in cPanel

It is under Advanced. In the Common Settings dropdown choose Once Per Minute, which fills the five time boxes for you.

2

Paste the command

Into the Command box, replacing the path with the folder your installation is actually in:

Cron command
cd /home/username/public_html && php artisan schedule:run >> /dev/null 2>&1

The path is the one you uploaded into in step 1. cPanel's File Manager shows it at the top of the window when you are inside the folder.

If your cPanel asks for the whole line including the timing, use this instead:

Full cron line
* * * * * cd /home/username/public_html && php artisan schedule:run >> /dev/null 2>&1
3

Save it and check the panel

Click Add New Cron Job. Then, in the panel:

Setup Settings Scheduler

That screen shows when the scheduler last ran. Within a minute or two it should show a recent time. If it still says it has never run after five minutes, your cron entry is not firing.

The exact command for your server is shown on the Scheduler screen, with your real path already filled in. Copy it from there rather than editing the line above by hand.

Some hosts use a different PHP for cron than for the web. If the schedule never runs, replace php in the command with the full path to the binary — commonly /usr/local/bin/php or /opt/alt/php83/usr/bin/php. Your host's support can tell you which in one message.

Scheduled sends depend on this entirely. A campaign set for 9am is released by the scheduler at 9am. With no cron it waits forever, still marked scheduled, and nothing tells you why.

Part 2 — step 5

Upload the service account key

This is the most important step in Part 2. The server needs its own credential to ask Firebase to wake your phones. It is a different file from the one you put in the app, it is downloaded from a different place, and the two are not interchangeable.

google-services.jsonThe service account key
Belongs toThe Android appYour server
Where it goesapp/google-services.json in Android StudioUploaded in the panel
Downloaded fromProject settings › Your appsProject settings › Service accounts
WhenPart 1, step 3Right now

Both files must come from the same Firebase project. One project on the app side and a different one on the server side is a setup that looks entirely correct, passes every visual check, and delivers nothing at all. If you only made one Firebase project in Part 1, you are already fine — just do not create a second one now.

1

Open Project settings in Firebase

Back in the Firebase console, in the same project as Part 1, click the gear icon next to Project Overview at the top left, and choose Project settings.

2

Go to the Service accounts tab

Along the top of the settings page, after General, Cloud Messaging and Integrations.

3

Click Generate new private key

A dialog warns you to keep the key confidential. Click Generate key. A .json file downloads — its name is long and full of dashes. That is the one.

4

Upload it in the panel

Setup System Firebase push

Choose the file and save. VeroSMS reads the project id and the service account address out of it and shows both back to you, so you can confirm at a glance that it is the right project's key. The badge at the top of the screen changes from Not configured to Configured.

5

Press the test button. Do not skip this.

The screen has a test that asks Google to validate the credential, and shows Google's own answer word for word. It is the only way to find out whether this is right before a real message fails.

If it comes back SENDER_ID_MISMATCH, the key and the app were made in two different Firebase projects. Go back to Part 1, check the package name under Project settings › Your apps, and make sure you downloaded both files from that same project.

Treat this file like a password. Anyone who has it can send push notifications as your project. Do not email it, do not put it in a shared folder, and never place it anywhere under public/ where a browser could fetch it.

Replacing the key takes effect immediately. No cache to clear, no restart. Messages that were waiting go out on the next push.

Part 2 — step 6

Pair a phone

Pairing is how a phone learns which installation it belongs to. You do it once per phone, from the panel.

1

Open the pairing screen

Devices Pair a device

The screen shows a QR code and, under it, an eight-character code in plain text. Either one works — they are two ways of handing the phone the same thing.

2

Open the app on the phone

It is sitting on its pairing screen, where you left it at the end of Part 1.

3

Scan the QR code, or type the eight characters

Scanning is quicker: point the phone's camera at your monitor. If the camera will not focus, if the phone has no camera permission, or if you are working on the phone remotely, type the eight-character code into the app instead. Both routes do exactly the same thing.

4

Watch it appear in the panel

Within a second or two the phone shows up in the Devices list, with its SIM slots listed against it. That is pairing done.

A pairing code is single-use and expires after ten minutes. If it has been sitting on screen while you went to find the phone, reload the page for a fresh one. A used or expired code fails with a message saying so — it is not a fault, just get another.

If the app says it cannot reach the server, the phone cannot open your site at the address inside the code. Check that the site loads in the phone's own browser, over https://. A phone on mobile data cannot reach an address that only exists on your office network.

Part 2 — step 7

Send a test message

One message to your own phone proves the entire chain at once — panel, queue, Firebase, phone, SIM, and the report coming back.

1

Open the send screen

Messaging Send
2

Pick the phone and the SIM slot

On a dual-SIM handset both slots are listed separately. Choose the one with credit on it.

3

Put your own number in, in full international form

Include the country code, like +8801711000021. A number typed in local form, like 01711000021, is refused until you have set a default dial code — the screen tells you so in as many words. See General settings for how to set one.

4

Type anything and send

The message should reach you within a few seconds. In the panel it moves from queued to sent, and then to delivered when the carrier confirms.

Now reply to it from your phone. The reply should appear in Messaging › Inbox within seconds. That proves the receiving half as well, and it is the half people forget to test until a real reply goes missing.

If the message stays at queued, Firebase is not reaching the phone. Go back to step 5 and press the test button, then check the phone is online on the Devices screen. That one pair of checks explains almost every case.

After installing

First login

There is one panel and one login screen:

Your panel
https://yourdomain.com/admin/login

If you installed the sample data, there is a shipped password and everyone who owns this product knows it. The seeded login is admin@gmail.com with the password Admin@12345, and the same details are written into a file on your server at storage/app/private/ADMIN-CREDENTIALS.txt.

Change the password before the site is reachable by anyone else, and delete that file once you have. Leaving it is the same as leaving your front door key under the mat that every buyer has been told about.

Change your password

Open your own profile from the account menu at the top right of the panel and set a new password. Use something long. This login can send messages that cost you money.

Add staff, if you have any

Setup Team Roles

Roles decide what a login may do — view messages, send them, manage contacts, pair devices, issue API keys, edit settings, and so on. Create the role first, then create the person:

Setup Team Staff

Give people the narrowest role that lets them do their job. Everything anyone does is recorded under Setup › Team › Activity log, which is worth knowing exists before you need it.

Two shortcuts worth learning on day one. Ctrl+K (⌘K on a Mac) jumps to the search box from anywhere in the panel, and pressing n starts a new message.

After installing

General settings

Setup Settings General

Eight settings live here. Two of them change how messages behave, and the rest are about how the site looks and reads.

SettingWhat it does
Site nameUsed throughout the panel, in emails and across the public landing page.
Support emailThe address shown to anyone who needs to contact you.
Copyright textThe line in the footer of the public site.
TimezoneEvery timestamp and every scheduled send is calculated against this.
Date formatHow dates are printed on screen.
Default dial codeThe country code added to numbers typed without one. See below.
Require email verificationWhether a new login must confirm its email address before being used.
Maintenance modeTakes the public site offline while you work on it. The panel stays reachable.

Why the default dial code matters more than it looks

Every SMS needs a full international number. Your contacts almost certainly do not have one: real address books are full of numbers like 01711000021, written the way people write them locally.

The default dial code is what turns those into something sendable. Set it to your country — +880, +44, +1 — and a local number becomes a full one on the way out.

Without it, a local number simply cannot be sent. The send screen refuses it and says so, which is fine for one message you typed by hand and much less fine when you have imported four thousand contacts and every one of them is unusable. Set this before your first import.

Set the timezone before anyone schedules anything. Scheduled sends and every report are worked out against it. Changing it later does not move sends that were already scheduled.

After installing

Email delivery

Worth doing early. Without working email, a forgotten password locks you out of your own panel with no way back except editing the database by hand.

Setup Settings Email delivery

Enter your SMTP details

These come from whoever provides your email. A typical set:

FieldTypical valueNotes
Mailersmtp
Hostsmtp.yourprovider.comFrom your provider
Port587465 if using SSL
EncryptionTLSSSL for port 465
UsernameYour SMTP usernameOften the full email address
PasswordYour SMTP passwordSee the warning below
From addressnoreply@yourdomain.comMust be a domain you own
From nameYour site nameWhat recipients see

Send a test email

The screen has a test button. Use it before you move on. SMTP settings that are nearly right fail silently, and the first person to find out is usually you, locked out, at the worst possible moment.

Gmail and Outlook need an app password, not your normal one. Both refuse ordinary account passwords from outside applications. Generate an app-specific password in your account's security settings and use that.

Use a real mail service for anything that matters. Shared hosting mail servers are often on spam blocklists, which means your mail is accepted and then quietly thrown away on the way. Amazon SES, Mailgun, Postmark or Brevo cost little or nothing at low volume and make a large difference to whether your email arrives.

Review the mail templates

Setup Settings Mail templates

Every email the system sends is editable here — password resets, staff invitations, verification. The defaults are complete and sensible, so leave them alone at first. Worth a read when you have time, so you know what goes out with your name on it.

After installing — optional

Landing page & SEO

Website Landing page All sections

VeroSMS ships with a public marketing page in front of the panel — hero, features, FAQ, contact details and more. Every section can be edited, reordered or switched off entirely.

If you are running this purely for yourself and nobody else should see a public page at all, you can switch the sections off, or put the whole site into maintenance mode from General settings.

What to change first

  • Contact — replace the shipped email address and phone number with your own
  • Hero — your own headline
  • Footer — your links and copyright line

SEO

Website Landing page SEO settings

Meta title and description, the image used when someone shares a link, and keywords. The title and description follow your site name automatically, so in practice this is mostly about the sharing image.

After installing — optional

Languages

Setup Languages Languages

English is installed and active. You can add more languages, and set which one the panel and the public site open in.

Setup Languages Translations

Every piece of text in the application can be translated here, in the browser. There is no file to edit and nothing to upload.

Right-to-left languages such as Arabic, Hebrew, Urdu and Farsi are supported — mark the language as RTL and the whole interface mirrors, panel and landing page together.

Skip this if you only need English. It affects nothing else and can be done at any time later.

After installing

Go-live checklist

Before you start using this for real work, walk this list once:

  • The Scheduler screen shows a recent run time — cron is firing
  • Setup › System › Firebase push reads Configured and the test button passes
  • A phone is paired and has actually delivered a real SMS to a real handset
  • A reply to that SMS arrived in Messaging › Inbox
  • That same phone still delivers after being left locked and idle for an hour — the battery-optimisation test, and the one people skip
  • Play Protect is switched back on for every phone you turned it off for
  • A test email arrived
  • The default dial code is set to your country
  • The timezone is set and will not need changing
  • The shipped admin@gmail.com password has been changed, and ADMIN-CREDENTIALS.txt is deleted from the server
  • The landing page contact details are yours, not the shipped ones
  • HTTPS is active and the site loads over https://
  • Your Android project folder, your keystore and your google-services.json are backed up somewhere off this computer
  • You have taken one backup from Setup › System › Backup & restore and confirmed it downloads

Test the restore, not just the backup. A backup nobody has ever restored is an assumption, not a safety net. Do it now, while there is nothing to lose.

Reference

Updating

When a new version is released, download the updated package from your CodeCanyon downloads page and read the changelog first. If a release needs anything unusual, it says so there.

1

Back up first

The database and your public/uploads/ folder. Every update, no exceptions. Setup › System › Backup & restore does both.

2

Replace the application files

Upload the new source-code.zip and extract it over your installation.

Keep your existing .env file and your public/uploads/ folder. The .env holds your database details and your application key; overwriting it disconnects the site from its own data, and overwriting uploads loses your logo and anything else you have added.

3

Apply any database changes

If you have SSH access, from the installation folder:

Terminal
php artisan migrate --force

If you do not have SSH, cPanel's Terminal tool does the same thing, and your host can run it for you if that is switched off.

4

Clear the caches

Terminal
php artisan optimize:clear

Skipping this is what makes a freshly updated site show you the old one, or a half-broken mixture of both.

Updating the app is a separate job. Phones that are already paired keep working across a server update. When a release includes a new version of the Android project, open the new project folder in Android Studio and repeat steps 5 to 8 of Part 1 — same app name, same package name, same google-services.json. Install the new APK over the old one on each phone; because the package name is the same, Android treats it as an update and the pairing survives.

Reference

Troubleshooting

The things that come up most often, and what actually causes them.

Messages stay "queued" and the phone never sends anything

This is the Firebase question, and it is the most common one by a wide margin. Work down the list in order and stop when something fails:

  • Is a key installed? Setup › System › Firebase push must read Configured, and the test button must pass.
  • Do the app and the key share a project? A key from one project cannot wake an app built with another project's google-services.json. The test reports this as SENDER_ID_MISMATCH.
  • Does the package name match? Compare applicationId in app/build.gradle against the package name in Firebase under Project settings › Your apps. One different character is enough to break it.
  • Does the phone have Google Play services? Firebase does not work without it, which rules out most Huawei handsets sold after 2019.
  • Can your server reach the internet? Some shared hosts block outbound HTTPS. If the Firebase test times out rather than failing, that is the cause.
  • Is the phone online? The Devices screen shows when it last reported in.
Gradle sync fails when I open the project

Read the red text in the Build panel at the bottom. The usual causes:

  • No connection to Google's servers. Gradle downloads libraries on first sync. Office and school networks often block it. Try another network.
  • It stopped half way. Click Try Again in the yellow bar, or File › Sync Project with Gradle Files. A partly downloaded cache fixes itself on the second attempt more often than you would think.
  • You accepted an upgrade prompt. If it worked before you clicked something about updating Gradle or the Android Gradle Plugin, undo it with Ctrl+Z, or extract a fresh copy of the project from your download and start again from step 4.
  • Spaces or accents in the folder path. Move the project to a short, plain path and open it again.
The build fails and mentions google-services.json

The message usually names both package names it compared. It means the package name inside your google-services.json is not the applicationId in app/build.gradle.

Fix the applicationId to match the file, not the other way round — a package name registered in Firebase cannot be edited afterwards. If you genuinely typed the wrong thing into Firebase, add a second Android app to the same Firebase project with the right package name, download the new google-services.json, and use that.

Also check the file is actually at app/google-services.json and is not called google-services (1).json.

The phone refuses to install the APK

Almost always Play Protect. Google treats the SMS permission as highly sensitive and blocks apps that ask for it when they come from outside the Play Store. Turn Play Protect off, install, turn it back on — the full path is in Part 1, step 9.

If the message is about unknown sources instead, grant Allow from this source to the app you are opening the file with.

If it says App not installed and you already have an older build on the phone, uninstall the old one first. Two builds with the same package name but different signing keys cannot replace each other.

Messages arrive in bursts, hours late

Battery optimisation. Android is putting the app to sleep and letting it run only when the phone is next unlocked or charging.

Set the app to Unrestricted in Android's battery settings. On Xiaomi, Oppo, Vivo, Realme and Huawei handsets there is a second, manufacturer-specific setting — Autostart, App launch or Protected apps — that has to be turned on as well. It is not in the same place and it overrides Android's own.

Leaving the phone on a charger helps too, because Android relaxes its restrictions while charging.

The QR code will not scan, or pairing fails

A pairing code is single-use and expires after ten minutes. If it has been on screen a while, reload the page for a fresh one, or use the eight-character code underneath instead of the camera.

If it scans and then fails, the phone cannot reach your server at the address in the code. Open your site in the phone's own browser to check. On a test installation on your own computer, a phone cannot resolve a name only that computer knows — use the machine's network IP address, with both devices on the same network.

The app sends but every message fails

Check the failure reason shown against the message — the app reports Android's own error, not a generic one.

  • Permission denied — the SMS permission was refused when the app first ran. Grant it in Android's app settings; it will not ask again on its own.
  • No service / radio off — no signal, or flight mode.
  • Failures on one SIM only — that SIM has no credit, or the carrier has barred it for bulk sending.

Send one SMS by hand from the phone's own messaging app. If that fails too, the problem is the SIM or the carrier, not VeroSMS.

The send screen refuses my recipient's number

The number has no country code and no default dial code is set. Either type the number in full international form, like +8801711000021, or set Default dial code under Setup › Settings › General so local numbers are completed for you.

The installer says a folder is not writable

Set the folder to 755 in cPanel File Manager with Recurse into subdirectories ticked. If it still fails, try 775. The three that matter are storage/, bootstrap/cache/ and public/uploads/.

Some hosts run PHP as a different user than the one owning your files, and no permission setting fixes that from your side. Your host's support can correct the ownership in seconds.

"500 Server Error" straight after installing

Nearly always one of three things:

  • Wrong document root. The domain must point at public/, not the folder above it.
  • storage/ is not writable. Laravel cannot write its own cache and fails before it can tell you why.
  • PHP version too low. Check the version for this domain, not the server default — cPanel sets it per domain.

The real error is in storage/logs/laravel.log. The last entry names the actual problem.

Emails are not being delivered

Use the test button on Setup › Settings › Email delivery first — it reports the specific failure.

  • Authentication failed — Gmail and Outlook need an app password, not your account password.
  • Connection timed out — your host blocks outbound SMTP. Ask them to open port 587, or use a provider with an API.
  • Sends but never arrives — check spam, then your SPF and DKIM records. Shared hosting mail is frequently blocklisted.
The Scheduler screen says it has never run

Your cron entry is not firing. Check the path in the command against the real path of your installation, which cPanel File Manager shows at the top of the window.

If the path is right, replace the bare php in the command with the full path to the PHP binary — often /usr/local/bin/php or /opt/alt/php83/usr/bin/php. Many hosts use a different PHP for cron than for the web.

An API call is refused with 403

Read the code in the response.

  • scope_missing — the key was created without the scope this call needs. Keys do not gain scopes later; create a new one with the right scopes ticked.
  • ip_not_allowed — the key has an IP allowlist and the call came from somewhere else.

Remember that an API key is shown once, at the moment you create it, and never again. If you did not copy it, create another and delete the old one. Developers › Documentation in the panel carries the full API reference, generated from the code, with your real values in the examples.

I forgot my panel password

Use Forgot password on the login page — which needs working email, and is why Email delivery is worth setting up early.

If email is not working yet, reset the password directly in the database with phpMyAdmin. The password column stores a bcrypt hash, so paste a hash rather than plain text; any bcrypt generator produces one.

The page looks unstyled or broken

Usually a stale cache after moving domains or changing the address. Clear the caches with php artisan optimize:clear.

If it only happens on some pages, check that APP_URL in .env matches the address you are actually visiting, including https://.

Can I move the installation to another domain?

Yes. Copy the files and the database, update APP_URL and the database details in .env, then clear the caches.

Paired phones hold the old address, so pair them again from the new one. Webhook URLs you have given to other systems point at the old domain until you change them there too.

How do I take a backup?

The panel has backup and restore under Setup › System › Backup & restore. You can also do it by hand: export the database from phpMyAdmin and download public/uploads/. Both parts are needed.

Back up your Android project folder and your signing keystore as well. They are not on the server and nothing else has a copy.

Reference

Changelog

Version 4.0.1

A rebuilt VeroSMS. The panel, the API and the Android app were written again from the ground up, so this release is a fresh installation rather than an upgrade of an older one — back up anything you care about before replacing an existing install, and read Updating first.

  • Self-hosted SMS gateway — send through your own Android phones and your own SIM cards, with no per-message fee to anyone
  • Android app shipped as a full Android Studio project, so the app is yours: your name, your icon, your package name, your Firebase project
  • Pairing by QR code or eight-character code, dual-SIM support, delivery reports and offline queueing
  • Single, bulk and personalised sending, with merge fields and scheduling
  • Inbox for incoming replies, captured from the SIM that received them
  • Contacts, groups, bulk import and export
  • REST API at /api/v1 with scoped keys and signed webhooks, documented inside the panel
  • Editable landing page with SEO settings and a contact section of real, tappable links
  • Staff logins with role-based permissions, and an activity log
  • Multi-language and RTL support, translated from the browser
  • Backup and restore, system info, and sample data you can reset
Reference

Support

If this guide has not solved your problem, get in touch. Support is available to verified buyers.

Have your Envato purchase code ready. Support is provided to verified buyers, and we may ask for it before we can help.

It is on your CodeCanyon Downloads page — click the download button beside this item and choose Licence certificate & purchase code.

What to include

Support is far faster when the first message contains enough to work with:

  • Your VeroSMS version
  • PHP and MySQL versions
  • Your hosting type — shared, VPS, cPanel, Plesk
  • Which step of this guide you are on
  • The phone model and Android version, if the problem involves sending
  • What the Firebase test button says, word for word
  • What you did and what happened instead
  • The last entries from storage/logs/laravel.log
  • A screenshot of the error, if there is one on screen
  • Your Envato purchase code

Support covers the product — bugs, installation problems and questions about how features work. It does not cover server administration or customisation, though we will point you in the right direction where we can.

Thank you for choosing VeroSMS. If it has been useful, a rating on your CodeCanyon downloads page genuinely helps.