Application Detection
Stop hunting for wp-config.php
Point the scanner at a server and it finds the sites, reads each one’s database credentials out of its own config file, and offers you a matched file and database job per install.
Scan server
Looks for WordPress, Laravel, Craft CMS, and Ghost installs in common web-root locations. Database credentials are read automatically where the config format allows it.
Storage destination for created jobs
www/acme-blog
/var/www/acme-blog
File backupDatabase backup (acme_blog)
www/acme-app
/var/www/acme-app
File backupDatabase backup (acme_app)
sites/acme-docs
/home/deploy/sites/acme-docs
File backupDatabase backup (ghost_prod)
One find command, six places it looks
There is no daemon, no plugin to install, and no control-panel integration to authorise. The scan is a read-only SSH session that runs this and then reads what it matched.
$ find <roots> -maxdepth 3 \
\( -name wp-config.php \
-o -name config.production.json \
-o -name .env \) 2>/dev/nullThe roots are shell globs, expanded by your own shell — a pattern that matches nothing contributes nothing rather than erroring the scan. That is why a server with only /var/www on it never has to care that the Cloudways and Forge paths are in the list.
The six roots
- /var/www
- The default nearly everywhere, and where GridPane and SpinupWP put site roots
- /home/*/public_html
- Per-user document roots on cPanel-style and hand-rolled setups
- /home/*/htdocs
- The same convention under its other common name
- /home/master/applications/*/public_html
- Cloudways’ application layout
- /home/forge/*
- Laravel Forge’s per-site directories
- /srv/www
- The FHS-tidy alternative to /var/www
What can be read, platform by platform
Four platforms get their database credentials extracted automatically. Everything else that carries a .env is still detected and still gets a file job — it just arrives without a database job attached.
| Platform | Found by | Engine | Credentials read from | Default excludes |
|---|---|---|---|---|
| WordPress | wp-config.php | MySQL | DB_NAME, DB_USER, DB_PASSWORD, DB_HOST read from the define() calls | none by default |
| Laravel | .env beside an artisan file | MySQL or PostgreSQL | DB_DATABASE, DB_USERNAME, DB_PASSWORD, DB_HOST; engine chosen from DB_CONNECTION | vendor, node_modules, storage/logs/* |
| Craft CMS | .env beside a craft file | MySQL or PostgreSQL | CRAFT_DB_DATABASE, CRAFT_DB_USER, CRAFT_DB_PASSWORD, CRAFT_DB_SERVER, falling back to the unprefixed v3 names | vendor, node_modules, storage/runtime/logs/* |
| Ghost | config.production.json | MySQL only | database.connection read from the JSON, but only when database.client is mysql | node_modules, content/logs/* |
| Anything else with a .env | .env with no artisan or craft alongside it | — | Not read — the file job is still created, the database job is not | node_modules, vendor |
Craft names moved in v4
Craft 4 and 5 prefix their variables CRAFT_DB_*, Craft 3 leaves them unprefixed. Both are checked, prefixed first — but a site that has renamed them beyond either convention is detected as Craft without credentials.
Ghost on SQLite gets no database job
Credentials are only read when the config declares a mysql client. On a SQLite install the database file sits inside the site directory and no default exclude touches it, so the file job carries it — copied live, so treat it as best-effort rather than a dump.
WordPress ships with no excludes
A WordPress tree is small and almost entirely worth keeping, so nothing is excluded by default. If you run a page-cache plugin that writes gigabytes under wp-content, add that directory to the job’s exclude list after it is created.
What one click actually creates
Detection is a shortcut to two ordinary backup jobs. Nothing it makes is special, hidden, or harder to change afterwards.
Step 1
A file job pointed at the install directory
Named after the last two segments of the path — “www/acme-blog files” — archiving the directory the signature file was found in, with that platform’s default excludes already filled in.
Step 2
A database job, when there was something to read
Created only when the scan came away with both an engine and a database name. No half-configured job with a blank password is ever left behind for you to discover on the first failed run.
Step 3
Sensible defaults you can immediately override
Both jobs arrive enabled, running daily at 02:00, with seven-day retention, failure alerts on and success alerts off. Every one of those is a normal field on a normal job — reschedule, rename, or re-point them the moment they exist.
Step 4
One decision left to you: where it goes
You pick the storage destination before creating anything, so the jobs land in the bucket you meant. Scan a server twice and you can send staging and production to different buckets.
Where the scan comes up empty
Detection is a convenience layer over file and database jobs. When it misses, nothing is lost — you configure the same two jobs yourself.
Three filenames, three levels deep
The scan is a single find with -maxdepth 3 looking for wp-config.php, config.production.json, or .env. A release-directory deploy that buries the .env at /var/www/site/releases/20260902/.env is four levels down and won’t be seen.
Six roots, all conventional
If your sites live somewhere the list above doesn’t cover — /opt, /data, a mounted volume — the scan finds nothing there. That isn’t a dead end, it just means creating the file and database jobs by hand, which takes about a minute.
Platforms that use none of those files
Drupal, TYPO3, Rails, and plain static builds keep their configuration somewhere else entirely, so there is no signature to match and they aren’t detected at all. Nothing stops you backing them up — detection is a shortcut, not the gate.
Anything running inside a container
The scan reads the host filesystem over SSH. A WordPress living in a container is a Docker job, not an application job — back up the named volumes and the compose file instead.
Hosted and headless CMSs
Sanity, Contentful, and their neighbours keep no files and no database on your server, so there is nothing on disk to detect. Their own export tooling is the right way to back those up.
No inbound SSH at all?
Detection needs an SSH connection from us to the server. On private infrastructure, the Agent runs file and database jobs from inside your network instead — you just configure them rather than scanning for them.
Prefer to follow along step by step? Read the detection guide in the help centre.
FAQs
Can’t find the answer you’re looking for? Reach out to our support team.
Does the scan change anything on my server?
No. It opens an SSH connection, runs one find command, and reads the config files that matched. Nothing is written, installed, restarted, or left behind — and if a file can’t be read, that file is skipped rather than failing the whole scan.
Where do the database passwords end up?
They are read out of the application’s own config during the scan and stored against the database job encrypted with AES-256-GCM, the same as any credential you type in yourself. They are never displayed back to you and never written to the database in plaintext.
What happens when I rotate that password later?
The database job keeps the credential captured at scan time, so rotating the password will start failing the job until you update it. Either edit the job’s credentials directly or run the scan again — nothing re-reads wp-config.php or .env on its own.
Does this work on Cloudways, Forge, GridPane, or SpinupWP?
Yes, on any of them, because the scan matches web-root conventions rather than a control panel’s API. Cloudways’ /home/master/applications/*/public_html and Forge’s /home/forge/* are searched explicitly, and GridPane and SpinupWP both sit under /var/www. All that’s required is an SSH connection VPS Snaps can use.
What if one server hosts a dozen sites?
Each install is listed separately with its own path, detected type, and its own Create backup jobs button, so you can take the four that matter and leave the staging copies alone. There is no bulk-create-everything button on purpose.
What do I see if nothing is found?
A plain message saying no recognisable applications were found in the common web-root locations — not an error. It usually means the sites live outside the six search roots, or the platform doesn’t use one of the three signature files.
The job types underneath
Detection creates these two together. Both work perfectly well on their own, on any server you can reach.
File backups
The job type detection creates for you, configured by hand: any path, your own exclude patterns, one gzipped tar per run.
Read moreDatabase backups
The other half of the pair. pg_dump and mysqldump over SSH for PostgreSQL, MySQL, and MariaDB, on whatever schedule you set.
Read moreVPS snapshots
When you would rather have the whole machine back than its parts — provider-native snapshots across seven clouds.
Read morePowerful features to give you peace of mind
Rest easy knowing your data and your reputation are safe.
- Bring your own storage
- Backups land in your own S3-compatible bucket — Backblaze B2, Wasabi, Cloudflare R2, or plain S3. You hold the keys and the data.
- Snapshots stay with your provider
- Provider snapshots are created through the provider's own API and never leave your account. We store the snapshot ID, not the image.
- Seven providers, one dashboard
- DigitalOcean, Hetzner, Vultr, Linode, AWS EC2, Google Compute Engine and Microsoft Azure — scheduled and reviewed from the same place.
- Schedules that fit your traffic
- Hourly, daily, weekly, monthly, or a fixed interval in minutes — anchored to your timezone, so a 02:00 job stays at 02:00 across a DST change.
- Retention that prunes itself
- Set how many days to keep. Older snapshots and archives are cleaned up after each successful run, so storage bills stay flat.
- Step-by-step run logs
- Every run records what it did, in order, with warnings and errors kept in place — so a failure tells you which step broke.
- Complete run history
- Status, duration, byte size, and what triggered each run, kept per job. Proof the backup ran, long after the night it ran.
- Checksummed on upload
- Every archive is hashed as it streams to your bucket and the checksum is stored with the run, so you can verify what landed.
- Run on demand
- Trigger any job by hand before a migration or a risky deploy, without touching its schedule or its retention window.
- Alerts on five channels
- Email plus Slack, Microsoft Teams, Google Chat, and Discord — on success, on failure, and on a job that missed its schedule entirely.
- Encrypted credentials
- SSH keys, database passwords, and storage secrets are sealed with AES-256-GCM before they touch the database.
- Team access with roles
- Invite your team into a shared workspace as owner, admin, or member, so backups outlive whoever set them up.

“I'm constantly spinning up WordPress and Laravel applications for clients, and backups are one of those things that are easy to put off until something goes wrong. VPS Snaps can detect the applications on a server and help create the file and database backup jobs, which makes getting proper backups in place much faster.”
Find out what is actually running on that server.
Connect it over SSH, run one scan, and turn every site it finds into a pair of backup jobs before you have finished your coffee.
No credit card required. Cancel anytime.