# Check the server before the shop opens

> Source: https://www.allsweb.com/sixpreflight
> Markdown for agents: https://www.allsweb.com/sixpreflight.md
> Publisher: AllsWeb (www.allsweb.com)

SixPreflight — Checks whether a server is ready to run 6amMart

SixPreflight is a server-readiness checker for 6amMart. Upload one folder, open it in a browser, and up to 163 checks end in one sentence: ready to open, or not ready — and exactly what to fix first.

Always the current release, and it runs on your own server. It reads: it never reads or writes an application table, and never sends mail or SMS to anyone. Three surfaces can act outside the tool's own folder, and a fourth writes inside it — each only when you press its button. See “What it will change, if you ask it to”.

## At a glance

- **distinct checks in the code:** 163
- **steps, cheapest and most-likely-broken first:** 10
- **sentence at the end of it:** 1
- **grade, with every blocker named:** A–F
- **Price:** Free
- **Where to get it:** https://codecanyon.net/search/sixpreflight
- **Documentation:** https://www.allsweb.com/sixpreflight/docs

## For a shop owner, not an engineer

You have bought 6amMart, you have rented a server, and somebody has installed it. The site loads. That is not the same as being ready. A shop can look completely normal in a browser while its payment gateway has no working credentials, its push notifications go nowhere, its .env file is readable by anyone on the internet, its scheduled jobs have never run once, and its database is configured to use a fraction of the memory you are paying for. None of that shows up until a real customer places a real order and something quietly goes wrong.

SixPreflight is the check you run before that happens. You upload one folder into your site, open it in a browser, set a password, and press a button. It looks at the server the way a careful engineer would — the hardware, PHP, the database settings, the web server, file permissions, what the internet can reach, and whether payments, email, SMS, maps and push notifications actually work when you call them for real.

Then it gives you one sentence — “Ready to open” or “Not ready to take orders” — a letter grade, and an ordered list of what to fix, each item with the exact line to change, the file it lives in, and what it costs your shop to leave it alone.

The scan itself only reads. Where the tool can act, it acts on a button you press, never on its own.

## What it scored when we pointed it at our own machines

A checker that has never published a result is an assertion. These are from the same measurement round as the SixPanel benchmark — the tool deployed to real servers running a real shop, and scored the way a browser scores it rather than from a shell.

| Server | Grade | Rows needing attention |
| --- | --- | --- |
| SixPanel | 97 · A | None |
| SixPanel Docker | 96 · A | None |

### Read a capped score correctly

The score caps at 88 while any single row is in the red, no matter how good the rest is. That is deliberate — a shop that cannot trade should not read as a B+ — but it means a capped number tells you almost nothing about the other ninety-nine checks. Earlier in the same round one server read 88 and another 96, and the difference between their underlying scores was 0.03 across about a hundred checks. The entire visible gap was one stale background job. Always read the red rows, never the headline alone.

### A defect this round found in the tool itself

SixPreflight's own scan runner had no error handling at all. On a server where the hosting company has disabled a PHP function, calling it in PHP 8 is not a suppressible warning — it is a fatal error — so a single disabled function ended the whole scan with a stack trace instead of a report. That is precisely the shared cPanel and Plesk hosting most likely to need this tool in the first place. It is fixed: a disabled function is now one row that says it could not be measured, and the scan finishes.

### And one it gets wrong on a hardened server

On a server where PHP is confined by a kernel sandbox, SixPreflight cannot read the web server's configuration — and it reports one timeout setting as unset when the web server has in fact set it. Absence of evidence read as evidence of absence, which penalises a server for being hardened. It is listed here because a tool that reports its own blind spots is worth more than one that does not have any.

## Stepped, not one long wait

The page itself runs no checks. It draws an empty shell, and then the browser asks the server for one step at a time.

- **First paint is instant** — Measured on the test install: 6.8 KB in 2 ms, against 36 KB and about 1.6 s when the page did all the work before rendering. On a server that is by definition possibly misconfigured, waiting on the slowest check before showing anything is the wrong trade.
- **The progress bar is real** — Completed steps over total steps, not an animation. When it stops, something is genuinely stuck, and the label says which check.
- **A hung check cannot take the page down** — Every step is its own short request, so nothing runs into max_execution_time. A step that throws is reported as a finding and the scan carries on. Every finished step is written to disk as it completes, so an interrupted scan is still readable.

### Two buttons

- **Check now** — Reads local configuration and looks up the server's public IP — about a second.
- **Deeper check** — Adds the two steps that make real outbound calls: the public-exposure tests against your own URL, and the live integration tests.

Honest detail: “Check now” is not entirely offline. The public-IP row asks an outside echo service — ifconfig.me, then api.ipify.org, then icanhazip.com, tried in order and cached between scans, deliberately three providers so one bad minute does not overwrite a known-good answer.

### The three ways it runs

SixPreflight works out what it is looking at and changes what it says, because honest advice is different in each case.

- **On a plain server — no application installed yet** — This is the mode for choosing a server or preparing a new one. Hardware, PHP, the database server, the web server, permissions and public exposure are all still checked. The .env step returns nothing, the application step returns only the profile row, and the database step reports “not checked — no application here to hold credentials” as a pass rather than letting a missing connection become the worst row on a correctly empty box. You can still audit a bare box's database by pointing env_path at a stub .env that carries the credentials.
- **Inside your shop — at the 6amMart admin codebase** — Upload the folder into public/, the directory your web server actually serves. The application root is found by walking up from the tool's own folder, at most five levels, to whichever directory holds artisan — so both public/preflight/ and a folder in the application root work, and an upload buried deeper than five levels silently gets standalone mode instead. The correct home is public/ — a folder in the application root is only reachable by URL when the document root is wrong, which is itself the most serious thing this tool looks for. Here every check runs, including the ones written from the 6amMart codebase specifically: the scheduler that pays stores and riders, modules marked enabled but missing, the exact PHP extensions its vendor packages require, and the websocket layer behind live delivery tracking. On any other Laravel application everything about the server still applies exactly as written, and the 6amMart-specific checks are skipped rather than guessed at.
- **Embedded in SixPanel** — On a SixPanel server the panel owns the web server, PHP, the database configuration, cron, the queue worker and the certificate, and rewrites those files from its own templates on every deploy — so a value pasted in by hand is silently lost at the next deploy. In that mode SixPreflight drops the paste blocks, the raw nginx and Apache blocks, the php-fpm restart lines and the “where to click in your hosting panel” paths, and points at the SixPanel page that owns each setting instead. It keeps everything about the application — .env, business settings, missing or wrong keys, a wrong APP_URL, broken storage, errors in the log — because that is the half the panel cannot put right by itself. It says which mode it is in, in one line at the top of the page, so the mode is never a mystery. The mode is decided by an environment variable set by the server block that answers the path (SIXPANEL_EMBED=1), or by 'embedded' => true in config.php. A request header is deliberately not the primary signal: a header is written by whoever makes the request, so it would survive the panel's frame and nothing else — open the same page in a new tab and the tool would flip back to standalone advice on the same server. X-SixPanel-Embed: 1 is honored only when you switch on 'trust_embed_header', which is off by default, because ungated it would let any visitor hand themselves the managed-server view on a server that is in fact theirs to fix.

## 163 distinct checks, in ten steps

163 distinct checks live in the code, run in ten steps, ordered cheapest and most-likely-broken first. The two steps that make outbound calls are marked slow and only run on a Deeper check.

| Step | What it looks at | Checks | Real examples |
| --- | --- | --- | --- |
| System & hardware | The machine you are paying for | 7 | vCPU count, RAM, swap, free disk, load average, OS release, whether any backup tool exists at all |
| PHP runtime | The language the shop runs on | 18 | PHP version band, 25 required extensions, memory_limit, effective max_execution_time, display_errors, OPcache on/off, OPcache memory and file count, hit rate |
| Application health | Laravel and 6amMart itself | 22 | .env tracked in git, pending migrations, failed jobs, queue backlog, log size, error count in the log, whether the scheduler has ever run, module list valid, trusted proxies, install settings present |
| Environment (.env) | The one file everything reads | 14 | duplicate keys (the last one wins, so your edit does nothing), invisible \r characters, an invalid or shipped APP_KEY, APP_DEBUG=true, a malformed APP_URL, keys nothing reads, keys that go null once config is cached |
| Host identity & permissions | Who owns the files | 9 | public IPv4 and IPv6, the PHP user, file ownership, the six directories that must be writable, world-writable files, a world-readable .env, anything writable and executable inside public/ |
| Web server | nginx or Apache in front | 17 | handler type, gzip, server tokens, FastCGI read timeout, Apache modules and MPM, php-fpm worker count vs memory, the upload size chain, live compression, static caching, HSTS, certificate expiry |
| Cache, queue & realtime | Background work | 11 | queue connection, whether a queue worker is actually running and supervised, session and cache drivers, Redis, Memcached, Reverb credentials and scheme, Pusher credentials |
| Database configuration | Where the money lives | 32 | InnoDB buffer pool sized against your real data and RAM, redo log, flush method, max_connections against php-fpm workers, skip_name_resolve, sql_mode, charset, PHP-vs-database clock skew, buffer-pool hit rate, temp tables on disk, database user privileges |
| Public exposure | What a stranger can fetch | 12 | HTTPS, .env readable over the web, .git/config readable, laravel.log served, an uploaded .php file actually executing, Debugbar or Telescope answering, installer database dumps left in place, this tool's own files served as text |
| Payments, email & SMS | The services that must work | 21 | a real SMTP conversation, a real Firebase token mint, a real Google Maps geocode call, payment methods usable, SMS gateway credentials, storage disk writable, maintenance mode, reCAPTCHA, timezone, currency |

The column adds to 163. Two rows carry a qualifier.
- One of the 32 database checks — db_standalone — exists only for the case where there is no application to hold credentials. It stands in for the other 31 rather than joining them.
- Two of the 21 payments/email/SMS checks are prefix bases (sms_, social_) that expand at run time into one row per active gateway or per configured social login. So that step can emit more than 21 rows on a busy shop, or fewer on a bare one.

### No single run performs all 163 — and here is exactly why

- **An installed shop can produce at most 162 distinct rows — and no single run emits all 162** — db_standalone is emitted only when there is no application, so an installed shop can never see it; that is the 163rd. The 162 is a ceiling, not a run.
- **A Deeper check on an installed shop emits 160** — When the deeper step is going to follow, the web-server class suppresses its two config-read twins — nginx gzip and server_tokens, or Apache keepalive and server_tokens — because the live measurement answers the same question off a real response, and the two can disagree (gzip on; with a gzip_types list that omits application/json is a pass by config and a warning by measurement, about one setting). Those twins sit inside the 162; they are the reason a Deeper check lands at 160 rather than 162, not an extra pair on top of it.
- **A “Check now” emits 123 — it skips 39** — Those 39 are the 12 public-exposure checks, the 21 payments/email/SMS checks, and the six web-server rows that can only be read off a live response — compression, static_cache, keepalive_live, server_banner, hsts and cert_expiry. The two config-read twins are present in this run, because the live measurement that would have replaced them is not coming.
- **Both those figures count distinct keys, and a real server lands lower still — use the lower end** — Three of the 17 web-server keys belong to whichever web server you are not running (nginx contributes client_max_body_size, gzip and fastcgi_read_timeout; Apache contributes apache_modules, apache_mpm and keepalive), and the database step carries engine-conditional pairs — MySQL 8.0.30+ reports innodb_redo_log_capacity, everything else reports innodb_log_file_size, never both. Counting the web-server split alone, a Deeper check on an nginx or an Apache install emits no more than 157, and a “Check now” no more than 120; each engine-conditional database row takes it lower again.
- **On a plain server, 40 rows have nothing to read** — The 14 .env checks, the 12 Laravel application checks, the 9 6amMart platform checks and the 5 realtime checks have nothing to read at all — 40 rows, leaving only the profile row from the application step.

So the honest form is “up to 163” — with a Deeper check on a 6amMart install running the full set available to it, which is 160 distinct keys and no more than 157 rows on a real single-web-server box.

## One number — and it tells you what it could not measure

Every check ends as one of four things: pass, warning, problem, or not measured.

- pass
- warning
- problem
- not measured

The number is a weighted average, not a count. The weight table runs from 200 down to 11, set by what it costs you when it is wrong — APP_DEBUG=true sits at 200, the OS name row sits at 12, and app_profile and public_ipv6 sit at 11. Any key not in that table falls to a default of 10, and one live scan key does exactly that: db_standalone, which is genuinely unranked and shows up in the tool's own drift report. A pass earns its full weight, a warning earns half, a problem earns nothing.

| Score | Grade | What it means |
| --- | --- | --- |
| 90 and above | A | Production ready |
| 75–89 | B | Good. Clear the amber items and re-check |
| 55–74 | C | Workable, but leaving real performance on the table |
| 35–54 | D | Not ready. Several settings will hurt under load |
| Below 35 | F | Do not go live on this configuration |

### Blockers cap the grade

Some failures are not “points off” — they mean the shop cannot trade. One blocker caps the score at 74, two at 54, three or more at 34, so a blocker forces the grade band down and the weighted average only decides where inside that band you land. With no blockers at all, a single red row still caps the score at 88 — an A is unreachable with any red on the page.

The blocker list is short and specific, and it is exactly nineteen named keys plus anything beginning sms_: .env readable over the web, logs served over the web, the site in maintenance mode, an uploaded .php file executing, new stores unable to register, no usable payment method, the database unreachable, storage misconfigured, mail failing, SMS failing, a sql_mode the platform breaks under, the wrong charset, the scheduler not running, a certificate expiring inside 14 days, and five further .env faults — a missing or shipped APP_KEY, APP_DEBUG=true, a broken database block, a broken mail block, and duplicate keys.

Note what is deliberately not a blocker: files above the document root being readable is graded as a warning, not a blocker, because that is disclosure rather than a breach. The list is short on purpose — if everything is an emergency, nothing is.

### Why “not measured” is never graded — and why that matters

A check the tool could not run is excluded from the score entirely.

That is the single most important thing to understand about the number. On a managed panel, PHP is confined to the site's own directory — which is correct and worth keeping — and that means /proc, /etc/os-release, the nginx config and the php-fpm pool config cannot be read at all. Seven checks then have no answer to give.

A tool that scored those as failures would punish you for a hardening measure you should keep. A tool that scored them as passes would be lying. SixPreflight does neither: those rows say “not readable from here”, one row in the PHP section explains why once and gives both ways round it, and none of them touch the score.

The same rule applies to the backup check. If no backup tool is found, the row is not measured — not a warning — because your hosting provider's snapshots are invisible from inside the server, and the tool refuses to call something broken that it simply cannot see.

A locked-down server must not score badly for being locked down. That is the rule, and it is why the number is worth reading.

## It also has a second half: the setup script

SixPreflight reads and explains. bin/setup-6ammart.php is the other half of the package: it makes the changes. The shipped docs page says it in one line — “SixPreflight reads a server and explains what to change. setup-6ammart.php is the other half: it makes those changes.”

- **A bash script with a .php extension, deliberately** — PHP takes the file, hits an exit on line 3, and hands a browser nothing. Run it with bash, never through a browser.
- **The default mode is a dry run** — Running it by accident changes nothing. --check reports current versus recommended. --apply does the work.
- **84 catalog entries, 40 of them safe to apply without asking** — Its source of truth is the same tuning catalog the fix cards use — 84 entries across php, php-fpm, os, mysql, nginx, laravel and 6ammart, of which 40 are marked safe to apply without asking and 44 are prompted with the trade-off stated in one line, or printed as a manual instruction. No entry in the second group is ever applied silently, including under --yes.

**Disputed count, stated openly** The shipped docs/setup.html page says 84 entries, 40 safe-to-automate, 44 not. The script's own header and a direct count of the three data/tuning-*.json.php files both say 86 / 41 / 45. The lower published figure is the one used above.

So SixPreflight is a checker with an opt-in fixer beside it, not a checker alone.

## Requirements, how to run it, and what it will change

### What the tool itself needs

| Requirement | What it needs |
| --- | --- |
| PHP | 8.2 or newer to run the tool |
| Web server | Anything that serves your site's public/ directory |
| Write access | preflight/config.php (or paste a password hash by hand) and preflight/history/ |
| Application | None required. It runs on a bare server |
| Panels it recognizes | cPanel · aaPanel · CloudPanel · DirectAdmin · Plesk · CWP · plain server |

### What it grades your server against

| Resource | Floor | What to pick |
| --- | --- | --- |
| vCPU | 2 | 4 |
| RAM | 4 GB | 8 GB |
| Free disk | 20 GB on the requirements page — but the disk check itself passes at 20 GB, warns between 10 and 20, and only fails below 10 | 40 GB+ |
| Storage type | SSD | NVMe |
| Hosting type | VPS or dedicated | VPS with root |

### In a browser — the normal way

- **Upload the folder** — Upload the whole preflight/ folder into your site's public/ directory.
- **Set a password on the first screen** — Open https://your-domain/preflight/ and set a password. It will not start without one, and whoever opens it first is the one who sets it — so do this as soon as the upload finishes. Minimum eight characters. If config.php is not writable, the page says so and gives you the one-line password_hash() command to paste instead.
- **Press a button** — Check now takes about a second. Deeper check adds the outbound tests.
- **Delete the folder when you are finished** — It is protected, but it reports server internals and has no reason to stay on a live site.

### From the command line — no application, no browser

The two comparison tools are command-line only and refuse to answer over HTTP.

- `php preflight/server-compare.php` — measure this machine
- `php preflight/server-compare.php --save=box-a.json` — undefined
- `php preflight/server-compare.php --compare=box-a.json,box-b.json` — undefined
- `php preflight/detect-size.php` — record RAM and vCPU

They are not the only files with that guard. Eleven files in the package refuse to run outside the command line — those two, eight test harnesses including tests/smoke.php, and bin/setup-6ammart.php. tests/smoke.php is the reason the guard matters: left web-reachable with no password, which is how it once shipped, one anonymous GET cost eleven seconds of CPU, a full probe of the application database, ten requests the server made to its own public URL, and outbound calls to Google Maps, the configured SMTP host and Firebase, repeatable as often as anyone liked. The scan now probes your server for exactly that file, because a folder like this gets copied between machines for years.

### How it runs

Nothing in the package checks a license, an account or an expiry date, and nothing in it reports anything back to AllsWeb. The outbound calls it makes are all to places you already deal with — your own site, your own SMTP host, Google's token and geocoding endpoints — plus one public-IP echo service to discover your own address.

### You must already have

- PHP on the server you want to check — nothing else

## Read this before you rely on the number

- **It cannot see what the server will not show it** — Checks that need shell_exec or /proc degrade to “not measured” rather than guessing. Managed panels disable different things, so some rows are blank on one host and populated on another.
- **On a managed panel, seven checks have no answer** — open_basedir confines PHP to the site's directory. That is correct and worth keeping. The rows say so and are excluded from the score.
- **A “Check now” cannot see six of the web-server rows, and one of them is a blocker** — Compression, static caching, live keep-alive, the server banner, HSTS and certificate expiry are read off a real response, so they only appear on a Deeper check — and cert_expiry is on the blocker list. Run the Deeper check before you trust a green result.
- **The tool contradicts itself on free disk** — The requirements table says you need 20 GB free; the disk check calls 10–20 GB a warning and only fails below 10. Two answers to one question, on one page.
- **It reports what the server says it is configured with** — If a panel applies configuration at a layer this tool cannot see, trust the panel's own interface over this. cPanel and aaPanel manage PHP and MySQL config through their own UI and can overwrite hand-edited files; CloudPanel and a plain server leave the config files authoritative. If a setting keeps reverting after a restart, that is the panel rewriting it — change it through the panel instead.
- **The benchmarks measure this machine at this moment** — A noisy neighbour makes every number pessimistic — check the load-average row before drawing conclusions.
- **The exposure step is not a penetration test** — It fetches a fixed list of known-risky addresses off your own URL and reports what came back. It does not look for unknown vulnerabilities and it is not a code audit.
- **One thing genuinely cannot be tested from a server** — The Google Maps client key is restricted by browser referrer, so the tool can tell you it is missing, or that it is dangerously identical to your server key — but it cannot verify a correctly-restricted one from the server side, and says so rather than passing it.
- **Row counts in the size table are estimates** — They come from information_schema. Exact counts would mean a full scan of every table on a live site.
- **An upload buried more than five directories below artisan gets standalone mode** — Silently — the application-root search stops at five levels.
- **It is a checker first** — The scan itself changes nothing. Four surfaces in the package write when you press their button, and bin/setup-6ammart.php applies changes when you run it with --apply. All five are listed above.

### Is it safe on a live shop?

Yes, and here is exactly why.

- **The real-data probes are read-only by construction** — Every probe goes through one query() method that refuses anything that does not begin SELECT, EXPLAIN, SHOW or WITH — and there is no code path in that class that can issue INSERT, UPDATE, DELETE, ALTER, CREATE or DROP, which is the guarantee that actually carries the promise. The session is put in TRANSACTION READ ONLY where the server supports it, so even a mistake would be rejected by the database rather than by this code. Every statement carries a 15-second server-side limit, so a probe against an unexpectedly huge table cannot sit holding resources — and a probe that trips it is reported as “too slow”, which is itself the finding. Verified: row counts and SUM(order_amount) are identical before and after.
- **The database benchmark never touches an application table** — Every object it creates is named zz_preflight_bench_<random> with a fresh random suffix per run; it checks the name is free before creating anything and aborts rather than touching an existing table; no statement in it can name a table it did not create; cleanup is gated on the table having actually been created, runs in a finally block and a shutdown handler, and writes commit in small batches so nothing holds a long lock. Verified: orders and items row counts identical before and after, and no zz_preflight_ table survives the run.
- **The scope is the table, not the database, and the difference is the whole promise** — It never reads from or writes to any application table — that is the README's own wording and it is the right one. The benchmark creates and drops one table of its own inside the application's database, under a name it generates, and removes it again; nothing else in that database is touched.
- **Inside its own folder it writes one thing** — preflight/history/, one file per saved scan. Those files describe the server's weaknesses in detail, so each is named .json.php and starts with a PHP exit statement — fetched over HTTP the web server executes it, stops immediately, and returns nothing. That holds on nginx too, which ignores .htaccess.

### It deliberately does not

- Change anything by itself — it reports, you decide
- Install 6amMart
- Replace a backup, or test whether your data is recoverable

## Questions people actually ask

### How do I know if my server is ready for 6amMart?

Run SixPreflight on it. It holds 163 checks across hardware, PHP, the application, .env, permissions, the web server, caching, the database, public exposure and every outside service. A Deeper check on a 6amMart install runs the full set available to it — 160 distinct checks, and no more than 157 rows on a real box running one web server; a quick “Check now” runs 123, no more than 120 on that same box, skipping the 12 exposure checks, the 21 service checks and the six web-server rows that need a live response. Either way it ends in one sentence, a letter grade A–F, and an ordered list of what to fix first.

### Does SixPreflight change anything on my server?

The scan does not. It never reads or writes an application table, and never sends mail or SMS to anyone. Four surfaces do write when you press their button: the Error logs page can truncate a log file, the Test order alert page sends a real push to a real device, the optional database benchmark creates and drops its own table, and setting a password rewrites the tool's own config.php. The package also ships bin/setup-6ammart.php, which applies changes on purpose when you run it with --apply.

### Is it safe to run on a live shop that is taking orders?

Yes. The database probes are read-only by construction — the query() method refuses anything that does not begin SELECT, EXPLAIN, SHOW or WITH, there is no code path in that class that can issue a write, and the session runs in TRANSACTION READ ONLY where supported. The optional benchmark works only on a table it creates itself with a random name, and removes it in a finally block and a shutdown handler. Both were verified by comparing row counts and SUM(order_amount) before and after.

### Do I need 6amMart to use it?

No. It detects what it is looking at. On a plain server with no application it still checks hardware, PHP, the database server, the web server, permissions and exposure — though the 14 .env checks, the 12 Laravel application checks, the 9 6amMart platform checks and the 5 realtime checks have nothing to read, leaving only the profile row from the application step. On any Laravel application, everything about the server still applies and the 6amMart-specific checks are skipped rather than guessed at. On 6amMart, every check that can run does.

### What score do I need before I go live?

90 or above is an A — production ready. Below that, read the blockers first: a single blocker caps the score at 74 no matter how good everything else is, two cap it at 54, three or more at 34. Even with no blockers, one red row caps you at 88. Blockers are the things that stop the shop trading — no usable payment method, mail failing, the database unreachable, .env readable over the web, a certificate expiring inside 14 days. Run a Deeper check before trusting the number: that last one, and five other web-server rows, are not measured at all on a quick check.

### Why do some rows say “not readable from here”?

Because your hosting panel confines PHP to your site's own directory, which is correct and worth keeping — so /proc, /etc/os-release, the nginx config and the php-fpm pool config genuinely cannot be read. Seven checks then have no answer. They are reported honestly and excluded from the score entirely, so a locked-down server is never punished for being locked down.

### Does it work on cPanel, aaPanel, CloudPanel or a plain VPS?

Yes — that is its main market. It recognizes cPanel, aaPanel, CloudPanel, DirectAdmin, Plesk, CWP and a plain server, and gives per-panel install commands and paths. Worth knowing: cPanel and aaPanel manage PHP and MySQL configuration through their own interface and can overwrite hand-edited files, so if a setting keeps reverting after a restart, change it through the panel instead.

### Does it only tell me what is wrong, or can it fix it?

Both, and the fixing half is opt-in. The dashboard asks you to make each change by hand first, because a person who makes a change understands what they changed. When that is not practical, bin/setup-6ammart.php does the same work from the command line: default dry run, --check to report, --apply to act. It applies only the catalog entries flagged safe to automate — 40 of the 84 published entries — and prompts or prints the rest, including under --yes.

### I run SixPanel. Do I need to download this?

No. SixPanel mounts SixPreflight inside the shop and surfaces it as the panel's Shop check-up page. In that mode it drops the paste blocks for anything the panel owns — the web server, PHP, database configuration, cron, the queue worker, the certificate — and points at the panel page that owns each setting, because a value pasted by hand there is lost at the next deploy. It keeps every application-level check.

### What PHP and database version should I actually install?

Ubuntu 26.04 LTS, and then whatever its own archive ships — PHP 8.5 and MariaDB 11.8 — for a native install. PHP 8.5 was doubted because one dependency declares a bound below it, but that bound is a declaration and not a measurement: running the code on 8.5.4 gave a byte-identical spreadsheet export on the plain CodeCanyon tree and on our fork. Every PHP and MariaDB version measured ran at effectively the same speed, so none of this is a speed decision. What is real is the flavour: both MySQL versions need code changes before 6amMart runs on them at all, because item search sets a MariaDB-only optimizer flag and two index migrations read a server catalog in a case MySQL does not return.

### Can I plug the result into my own dashboard?

Yes. ?api=findings returns the last saved check as JSON over HTTP Basic auth, with a stable contract version. It never starts a scan, and the payload carries run.age_seconds so your dashboard can say “this reading is two weeks old” instead of presenting stale news as current.
