# Server and configuration guide

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

Part of: SixPreflight documentation

This is the guide to building a server that actually runs 6amMart well — what to install, what to choose between, and where every credential comes from. Every recommendation here was measured on real servers running this platform, not copied from a vendor's checklist.

:::note You can do all of this before 6amMart is installed
Build the server, install a panel, then run SixPreflight on its own — it checks PHP, the extension list, the database, Redis, cron and the document root with no part of 6amMart present. Fix what it flags, then install 6amMart onto a server you already know is compatible.
:::

## The recommended stack

| Layer | Choose | Why |
|---|---|---|
| Server | VPS, 2 vCPU / 4 GB minimum, 4 vCPU / 8 GB recommended | Shared hosting cannot run a queue worker, and usually will not let you tune the database — which is where most of the available speed is. |
| OS | Ubuntu 26.04 LTS | Security updates to Apr 2031, against May 2029 for Ubuntu 24.04 and Aug 2028 for Debian 13. No version swap on any of the three produced a reportable speed difference, so this is a support-runway choice. See [which OS to pick](https://www.allsweb.com/sixpreflight/docs/versions#operating-system-the-three-supported-releases). |
| Panel | aaPanel (free), CloudPanel also supported | A file manager, an App Store, a cron page and a log viewer — the things you use every week once the server is running. |
| Web server | nginx + PHP-FPM | Apache with mod_php forces the prefork worker model — every connection, even one fetching an image, costs a full PHP-sized process. |
| PHP | Whichever your release ships — 8.5 on Ubuntu 26.04 | All three of 8.3, 8.4 and 8.5 run 6amMart, at the same speed. 8.5 was measured against both codebases on 27 Aug 2026, correcting an earlier claim that it could not install the dependencies. See [why](https://www.allsweb.com/sixpreflight/docs/versions#php-8-3-vs-8-4-vs-8-5). |
| Database | Whichever MariaDB your release ships — 11.8 on Ubuntu 26.04, 10.11 on 24.04 | 11.8 against 10.11 is a wash on this platform's own queries. MariaDB over MySQL is the choice that matters: MySQL does not run 6amMart as shipped. See [the measurements](https://www.allsweb.com/sixpreflight/docs/versions). |
| Cache / queue | Redis | The cheapest large win after OPcache. |
| Object storage | Cloudflare R2 | Zero egress fees — for an image-heavy marketplace that is the entire cost story. |

## Sizing the server

| Resource | Minimum | Recommended | Why |
|---|---|---|---|
| vCPU | 2 | 4 | PHP-FPM, the database and the queue worker all want CPU at the moment an order is placed. |
| RAM | 4 GB | 8 GB | The database buffer pool alone wants most of 4 GB once the orders table is real. |
| Disk | 20 GB | 40 GB+ | Product images grow fastest, and a full disk takes the site down rather than slowing it. |
| Storage type | SSD | NVMe | The difference shows up directly in SixPreflight's own database benchmark. |

### Swap

Add a swap file even on a server with plenty of RAM. Without it, running out of memory does not make the machine slow — it makes the kernel kill the largest process, which is almost always the database. What you see is a site that starts refusing connections with nothing in the Laravel log, looks fixed by a restart, and does it again during the next busy hour.

```bash
fallocate -l 2G /swapfile && chmod 600 /swapfile
mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
sysctl -w vm.swappiness=10
```

## PHP

```
memory_limit = 512M
upload_max_filesize = 32M
post_max_size = 32M
max_execution_time = 300
max_input_time = 300
max_input_vars = 5000
display_errors = Off
log_errors = On
expose_php = Off

opcache.enable = 1
opcache.memory_consumption = 256
opcache.max_accelerated_files = 30000
```

The required extension list is taken from 6amMart's own `composer.json` and installed packages, not a generic Laravel checklist. `zlib`, `iconv`, `xmlreader` and `xmlwriter` are missing from most published lists but are hard requirements of the spreadsheet library — every Excel export fails without them. `bcmath` and `intl` show up on most checklists and 6amMart never calls either one; do not chase them.

## Database

SixPreflight computes these for your machine's actual RAM rather than a fixed number. Illustrative values for a 4 GB server:

```
[mysqld]
innodb_buffer_pool_size        = 2G
innodb_log_file_size           = 512M
innodb_flush_log_at_trx_commit = 1
innodb_flush_method            = O_DIRECT
innodb_io_capacity             = 2000
max_connections                = 200
character-set-server           = utf8mb4
collation-server               = utf8mb4_unicode_ci
slow_query_log                 = 1
long_query_time                = 2
```

Do not point the application at `root`. Create a scoped user instead:

```sql
CREATE USER 'shopapp'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON `yourdb`.* TO 'shopapp'@'localhost';
FLUSH PRIVILEGES;
```

With a scoped user, a SQL injection anywhere in the codebase reaches this shop's tables and stops. With `root`, it can reach the whole server.

`max_connections` is not a number to pick on its own. Every PHP-FPM worker that serves a request opens a database connection, so if the worker count is higher than `max_connections`, the extra requests fail at your busiest hour with a database error that looks unrelated. Keep `max_connections` at least ten above your worker count.

Character set must be `utf8mb4`, not three-byte `utf8` — the first customer who puts an emoji in a review or a store name gets a server error, not a validation message, on the smaller charset.

## Cron & queue worker

Store and delivery-man disbursements, subscription reminders and the monthly order reminder all run from Laravel's scheduler. Without the crontab line, none of them ever happen — vendors are not paid, and nothing is written to any log to tell you why.

```bash
* * * * * cd /path/to/app && php artisan schedule:run >> /dev/null 2>&1
```

Push notifications, order mail and the live-tracking broadcast are all queued. With no worker running, they are accepted and never sent.

```
[program:worker]
command=php /path/to/app/artisan queue:work --queue=default --tries=3 --timeout=90
directory=/path/to/app
autostart=true
autorestart=true
numprocs=2
```

## The `.env` file

| Key | Where it comes from |
|---|---|
| `APP_URL` | Your own https domain, no trailing slash — a trailing slash produces double slashes in gateway callbacks, and some gateways reject the mismatch. |
| `APP_KEY` | `php artisan key:generate`. Never copy one between installs — it decrypts your stored tokens. |
| `APP_DEBUG` | `false`. With it on, one server error on a public page shows the stack trace, the failing query, and the contents of `.env` to whoever triggered it. |
| `APP_TIMEZONE` | A real timezone identifier, matched to the database's own clock. |
| `DB_*` | From your panel when you create the database. Grant rights on that database only, never global privileges. |
| `FILESYSTEM_DRIVER` | Not `FILESYSTEM_DISK` — Laravel renamed this key, but 6amMart still reads the old name. |

Full detail on why some keys break silently once the config is cached: see [The .env check](https://www.allsweb.com/sixpreflight/docs/env-check).

## Google Maps

Two keys, restricted differently — using one key for both is the most common mistake here.

1. **Server key** — Google Cloud Console, enable Geocoding, Directions, Distance Matrix and Places. Restrict by IP address to your server's outbound IPv4 and IPv6, both shown on SixPreflight's own scan.
2. **Client key** — a second key, enable Maps JavaScript API and the Maps SDKs. Restrict by HTTP referrer, not by IP.
3. **Billing** — Maps returns an error on every request without a billing account attached, even inside the free tier.

## Firebase

Firebase carries every push notification 6amMart produces — order accepted, rider assigned, order delivered. Two pieces, and they must belong to the **same** Firebase project or push notifications go nowhere with no error anywhere:

- A **service account** (Project settings → Service accounts → Generate new private key), uploaded in the admin panel — never pasted into `.env`.
- The **web config** (Project settings → General → Your apps → Web app), which is meant to be public and visible in page source.

## Payments

Every gateway ships a test pair and a live pair — going live with test keys is the classic launch-day failure. The callback URL must match your https `APP_URL` exactly, including the absence of a trailing slash. Additional gateways live in the Gateways module; if it is marked enabled in the admin panel but the folder is missing on the server, those payment methods simply do not appear, with nothing to tell you why.

## Email

```
MAIL_MAILER=smtp
MAIL_HOST=smtp.your-provider.com
MAIL_PORT=587
MAIL_USERNAME=...
MAIL_PASSWORD=...
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=orders@your-domain.com
```

Use a transactional provider — Amazon SES, Brevo, Mailgun or Postmark. Not Gmail and not your host's own mail — both fail SPF at the recipient, so password resets land in spam. Set SPF, DKIM and DMARC records on your domain, or delivery is a coin toss regardless of which provider you pick.

## SMS & OTP

Consider Firebase phone authentication instead of an SMS gateway entirely — it is free within a generous quota and removes the per-message bill. If you do need a gateway, 6amMart supports 2Factor, MSG91, Vonage and Twilio. Turn on only one route — SixPreflight warns when several are active at once, since that sends OTPs down a path you did not intend.

## Storage — Cloudflare R2

R2 charges nothing for egress, which for an image-heavy marketplace is the entire cost story. It speaks the S3 protocol, so no code change is needed.

```
FILESYSTEM_DRIVER=s3
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_DEFAULT_REGION=auto
AWS_BUCKET=your-bucket
AWS_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
AWS_URL=https://cdn.your-domain.com
```

## Cloudflare

Worth using, and free — but one setting is missing by default and it costs more than people expect. 6amMart's own middleware stack does not trust the proxy out of the box, so every visitor's IP address reads as Cloudflare's own, and secure-request detection returns false on your https site. Add this inside `bootstrap/app.php`:

```php
$middleware->trustProxies(at: '*');
```

Use `'*'` only when Cloudflare is the sole way in. A vendor update can overwrite this file — SixPreflight checks for it and tells you to re-add it after every update.

## Backups

You need two different things, because they protect against different failures:

- **Provider snapshots** — most VPS providers sell these for a few dollars a month. They protect against the disk dying or the machine being lost.
- **Your own nightly database dump, kept off this machine** — snapshots faithfully preserve a bad deploy or a wrong `DELETE` too. A dated dump lets you go back to yesterday.

```bash
0 3 * * * mysqldump --single-transaction --quick yourdb | gzip > /backup/db-$(date +\%F).sql.gz
```

Test the restore before you go live, on a spare database — an untested backup is a guess.

## Go-live checklist

:::checks
- Full scan with 6amMart installed, nothing red
- APP_DEBUG=false, APP_URL on https with no trailing slash
- Certificate installed, http redirects to https
- Document root confirmed as public/ by the exposure test
- Cron line added, scheduler shown ticking
- Queue worker running under supervision
- Database tuned from the What to fix page, and restarted
- Maps server key IP-restricted, client key referrer-restricted
- Firebase service account and web config from the same project
- Payment gateways on live keys, callbacks pointing at your https domain
- No placeholder values left in .env
- Database user scoped to its own database, not root
- Swap file present
- Nightly database dump running, and restored once to prove it works
:::

## Where to go next

- [Which PHP, database and OS version](https://www.allsweb.com/sixpreflight/docs/versions) — the measured comparison behind every choice above
- [The setup script](https://www.allsweb.com/sixpreflight/docs/setup-script) — apply most of this automatically instead of by hand
