Server Requirements

RequirementMinimumRecommendedNotes
PHP8.18.2+Required
MySQL / MariaDB8.0 / 10.4MySQL 8.0+Required
Web ServerNginx, Apache, or IIS (Windows Server)
Composer2.xLatestOptional — only needed to add/update PHP packages
Node.js18.x20.x LTSOptional — only needed to rebuild frontend assets
npm9.xLatestOptional — bundled with Node.js
vendor/ and public/build/ are pre-packaged. The release zip includes all PHP dependencies (vendor/) and compiled frontend assets (public/build/). Neither Composer nor Node.js is required to run the application.

You only need them if you want to customise the codebase:
Composer — to add, remove, or update PHP packages: composer install
Node.js / npm — to modify and rebuild the frontend: npm install && npm run build

Required PHP Extensions

BCMath, Ctype, cURL, DOM, Fileinfo, JSON, Mbstring, OpenSSL, PDO, PDO_MySQL, Tokenizer, XML, Zip

Most extensions are bundled with PHP by default. If the installer flags any as missing, install them using the commands below.

Ubuntu / Debian

sudo apt update
sudo apt install -y \
    php8.2-bcmath \
    php8.2-curl \
    php8.2-dom \
    php8.2-fileinfo \
    php8.2-mbstring \
    php8.2-mysql \
    php8.2-tokenizer \
    php8.2-xml \
    php8.2-zip \
    php8.2-opcache
sudo systemctl restart php8.2-fpm   # or apache2

Replace php8.2 with your installed PHP version (e.g. php8.3). ctype, json, and openssl are built into PHP and do not need a separate package.

CentOS / RHEL / AlmaLinux

sudo dnf install -y \
    php-bcmath \
    php-curl \
    php-dom \
    php-fileinfo \
    php-mbstring \
    php-mysqlnd \
    php-tokenizer \
    php-xml \
    php-zip \
    php-opcache
sudo systemctl restart php-fpm

cPanel / Shared Hosting

Go to cPanel → Select PHP Version (or MultiPHP Manager), select your domain, then enable the required extensions from the list and click Save. All extensions listed above are available in cPanel's PHP selector.

Windows Server (IIS)

Install PHP via the Web Platform Installer or manually download from windows.php.net. Then enable the required extensions:

  1. Open your php.ini file (usually in C:\PHP\php.ini or the path shown by php --ini).
  2. Uncomment (remove the leading ;) each required extension:
    extension=bcmath
    extension=curl
    extension=fileinfo
    extension=mbstring
    extension=openssl
    extension=pdo_mysql
    extension=tokenizer
    extension=xml
    extension=zip
  3. Save php.ini and restart IIS:
    iisreset

Alternatively, if you installed PHP via PHP Manager for IIS, open IIS Manager → select your site → PHP ManagerEnable or disable an extension, then enable each extension from the list.

Verify extensions are loaded:

php -m | findstr /i "bcmath curl fileinfo mbstring pdo_mysql xml zip"

Verify installed extensions

php -m | grep -E "bcmath|curl|dom|fileinfo|mbstring|pdo|pdo_mysql|tokenizer|xml|zip"

Installation

  1. Upload files
    Upload all files to your server's web root (e.g. public_html/). The public/ folder should be your document root.
  2. Create a database
    Create a new MySQL database and user via cPanel, phpMyAdmin, or your host's control panel.
  3. Run the installer
    Visit https://yourdomain.com/install and follow the on-screen wizard to configure your environment, test the database connection, and run migrations automatically.
  4. Build frontend assets (optional)
    The release zip ships with pre-compiled assets in public/build/ — this step is only needed if you have modified the frontend source.
    npm install
    npm run build
  5. Set permissions

    The web server must be able to write to storage/, bootstrap/cache/, public/uploads/, and .env. Run the appropriate commands for your server OS:

    Linux (Ubuntu / Debian / CentOS)

    # storage, bootstrap/cache & uploads
    chown -R www-data:www-data \
        /path/to/app/storage \
        /path/to/app/bootstrap/cache \
        /path/to/app/public/uploads
    chmod -R 775 \
        /path/to/app/storage \
        /path/to/app/bootstrap/cache \
        /path/to/app/public/uploads
    
    # .env
    chown www-data:www-data /path/to/app/.env
    chmod 644 /path/to/app/.env

    Replace www-data with your web server user if different (e.g. nginx, apache). To check your web server user: ps aux | grep -E 'nginx|apache|php-fpm' | awk '{print $1}' | grep -v root | head -1

    macOS (local development)

    # storage, bootstrap/cache & uploads
    sudo chown -R $(whoami):staff \
        /path/to/app/storage \
        /path/to/app/bootstrap/cache \
        /path/to/app/public/uploads
    chmod -R 775 \
        /path/to/app/storage \
        /path/to/app/bootstrap/cache \
        /path/to/app/public/uploads
    
    # .env
    sudo chown $(whoami):staff /path/to/app/.env
    chmod 644 /path/to/app/.env

    Windows (IIS)

    # storage, bootstrap/cache & uploads
    icacls "C:\path\to\app\storage" /grant "IIS_IUSRS:(OI)(CI)F" /T
    icacls "C:\path\to\app\bootstrap\cache" /grant "IIS_IUSRS:(OI)(CI)F" /T
    icacls "C:\path\to\app\public\uploads" /grant "IIS_IUSRS:(OI)(CI)F" /T
    
    # .env
    icacls "C:\path\to\app\.env" /grant "IIS_IUSRS:F"

    cPanel / Shared Hosting

    Go to cPanel → File Manager, navigate to your app root:

    • Right-click storage, bootstrap/cache, and public/uploadsChange Permissions → set to 755 or 775.
    • Right-click .envChange Permissions → set to 644.

    Alternatively use SSH and run the Linux commands above.

  6. Set up cron and queue — see the next section.
After installation completes you will be redirected to /admin/login. Sign in with the email and password you entered during the installer's admin account step.

Login URLs & Security

WPress Zone uses two separate login pages — one for regular users and one for administrators. Keeping them separate prevents admins from accidentally logging in via the public-facing form, and makes it straightforward to restrict admin access at the server level.

URLWho can sign inNotes
/loginRegular users onlyLinked from the public landing page and footer
/admin/loginAdmins onlyNot linked publicly — share only with your team
How role enforcement works
Each endpoint validates both credentials and role. If an admin's email and password are submitted to /login, authentication is rejected with a generic error — no information is leaked about whether the account exists or has a different role.

Restricting Admin Access by IP (recommended)

For an extra layer of protection, allow only trusted IP addresses to reach /admin/login. Example configurations:

Nginx

location /admin {
    allow 203.0.113.10;   # your office IP
    deny  all;
}

Apache (.htaccess)

<Location /admin>
    Require ip 203.0.113.10
</Location>
Replace 203.0.113.10 with your actual IP address. If you are on a dynamic IP, consider using a VPN with a fixed exit IP instead.

Upload Security

The public/uploads/ directory is web-accessible, so it is important to prevent malicious files from being uploaded and executed. The following measures are applied:

MeasureWhere enforcedDetails
Allowed file typesServer-side (controller)Only PNG, JPG, SVG, WebP, and ICO are accepted. All other types are rejected before saving.
File size limitServer-side (controller)Logos are limited to 2 MB, favicons to 512 KB. Requests exceeding these limits are rejected.
Random filenamesApplicationUploaded files are saved with a random 12-character name, making them impossible to guess.
Script execution blockedWeb server configPHP and other script files are blocked from executing inside public/uploads/ even if one were somehow uploaded.

Block Script Execution in Uploads Directory (required)

Even though only image types are accepted, it is strongly recommended to configure your web server to block script execution inside public/uploads/ as a defence-in-depth measure.

Nginx — add inside your server {} block:

location ~* ^/uploads/.*\.(php|php5|phtml|pl|py|jsp|sh|cgi)$ {
    deny all;
}

Apache — create public/uploads/.htaccess:

<FilesMatch "\.(php|php5|phtml|pl|py|jsp|sh|cgi)$">
    Deny from all
</FilesMatch>

IIS — add a request filtering rule in your web.config:

<requestFiltering>
    <fileExtensions>
        <add fileExtension=".php" allowed="false" />
        <add fileExtension=".pl" allowed="false" />
        <add fileExtension=".py" allowed="false" />
        <add fileExtension=".sh" allowed="false" />
    </fileExtensions>
</requestFiltering>

Cron & Queue Setup

Laravel Scheduler (required)

WPress Zone relies on the Laravel task scheduler for uptime checks, vulnerability scans, and domain/SSL monitoring. Add a single cron entry to your server:

* * * * * cd /path/to/your/project && php artisan schedule:run >> /dev/null 2>&1

Replace /path/to/your/project with your actual installation path (e.g. /home/username/public_html).

On cPanel, go to Cron Jobs, set the interval to Every Minute (*), and paste the command above.

Without the cron entry, uptime monitoring and vulnerability checks will not run automatically.

Scheduled Tasks

TaskFrequencyDescription
monitor:uptimeEvery minuteChecks uptime for all monitored sites
domain:statusEvery minuteChecks domain expiry and SSL certificate status (per-site checks are throttled to every 6 hours inside the command)
vulnerabilities:populateDaily 02:00Syncs latest vulnerability definitions from WPVulnerability.net
plugin-vuln:checkDaily 03:00Scans plugins against vulnerability database
theme-vuln:checkDaily 03:15Scans themes against vulnerability database
core-vuln:checkDaily 03:30Scans WordPress core versions for known CVEs
site-vuln:checkDaily 03:45Runs full vulnerability report per site
logs:delete-oldWeekly (Sun)Removes logs older than the user's plan retention period

Queue Worker

Alert notifications (Slack, Telegram, Discord, email, etc.) are dispatched as queued jobs. WPress Zone supports two queue modes — choose the one that matches your hosting environment.

ModeBest forWorker required
sync (default)Shared hosting, cPanel, low site countNo
databaseVPS, dedicated server, 50+ sitesYes

Option 1 — Sync / Inline (shared hosting)

Jobs run immediately during the same HTTP request. No background worker or extra process is needed. This is the default and works out of the box on any shared host.

Your .env should have (or default to):

QUEUE_CONNECTION=sync
Trade-off: Each webhook request from your WordPress plugin will block briefly while the alert notification is sent. For most deployments this is imperceptible, but under heavy load it adds latency to plugin responses.

Option 2 — Database queue (VPS / dedicated server)

Jobs are written to the jobs database table and processed by a background worker. This keeps plugin responses fast, retries failed notifications automatically, and exposes failed jobs in the System Health page.

Step 1 — Set the queue driver in .env:

QUEUE_CONNECTION=database

Step 2 — Create the jobs table (skip if already migrated):

php artisan queue:table
php artisan migrate

Step 3 — Run the worker:

php artisan queue:work --sleep=3 --tries=3 --max-time=3600

Step 4 — Keep the worker alive with Supervisor (recommended on Linux VPS):

[program:wpress-zone-worker]
command=php /home/username/public_html/artisan queue:work --sleep=3 --tries=3 --max-time=3600
directory=/home/username/public_html
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/home/username/public_html/storage/logs/worker.log
stopwaitsecs=3600

Install and reload Supervisor:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start wpress-zone-worker
After every deployment restart the queue worker so it picks up new code:
php artisan queue:restart

Switching between modes

You can switch modes at any time by changing QUEUE_CONNECTION in .env. If switching from database back to sync, stop the worker first. If switching to database, make sure the jobs table exists before starting the worker.

Change Admin Email & Password

Your admin email and password are set during installation. If you need to update them after going live, follow these steps.

Change your email and password

  1. Log in at https://yourdomain.com/admin/login using the credentials you created during installation.
  2. Click your name in the top-right corner to open the dropdown menu, then click Edit profile.
  3. Update the Email field if needed.
  4. Scroll down to the Change Password section. Enter your current password, then enter and confirm your new password.
  5. Click Update Profile to save.
If you are locked out and cannot log in, you can reset the admin credentials from the command line:
php artisan tinker
>>> App\Models\User::where('role', 'admin')->first()->update(['email' => 'you@yourdomain.com', 'password' => bcrypt('YourNewPassword')])

App Settings

Visit Admin → Settings to configure:

SettingDescription
LogoUpload a single logo or separate light & dark versions (shown in navbar, login, and invoices)
FaviconUpload a favicon shown in browser tabs
Support EmailShown on invoices and in Terms / Privacy pages
Footer TextShort tagline or copyright text shown in emails and pages
SMTP / MailSee Email (SMTP) section below
App Name is set during installation and is read from the server environment. To change it after install, update APP_NAME in your .env file and run php artisan config:clear.

Stripe Payments

  1. Create a Stripe account and go to Developers → API keys.
  2. Copy your Publishable key and Secret key.
  3. In the Admin panel, go to Gateways, enable Stripe, and click Edit to paste the keys.
  4. Webhook (optional but recommended) — in Stripe Dashboard go to Developers → Webhooks, add endpoint:
    https://yourdomain.com/stripe/webhook
    Select events: invoice.payment_succeeded, invoice.payment_failed. Copy the generated Webhook Signing Secret and paste it into the Stripe gateway settings in the Admin panel.
Use pk_test_ / sk_test_ keys during development and testing.

PayPal Payments

  1. Create or log in to your PayPal Developer account and go to My Apps & Credentials.
  2. Create a new app (or use an existing one) and copy the Client ID and Secret for both Sandbox and Live modes.
  3. In the Admin panel, go to Gateways, enable PayPal, and click Edit to paste the Client ID, Secret, and select the mode (sandbox or live).
  4. Webhook (optional but recommended) — in your PayPal Developer Dashboard go to your app → Webhooks, add endpoint:
    https://yourdomain.com/paypal/webhook
    Select events: PAYMENT.SALE.COMPLETED, BILLING.SUBSCRIPTION.CANCELLED, BILLING.SUBSCRIPTION.EXPIRED, BILLING.SUBSCRIPTION.PAYMENT.FAILED.
Select Sandbox mode during development and switch to Live for production — this is configured in the Admin panel gateway settings.

Bank Transfer / Manual Payment

The Bank Transfer gateway allows customers to pay by wire transfer. Orders are placed with a pending status and the admin manually confirms payment.

  1. In the Admin panel, go to Gateways and enable Bank Transfer.
  2. Edit the gateway details to add your bank account information (IBAN, account name, bank name, reference instructions). This text is shown to the customer at checkout and included in their invoice email.
  3. When a customer completes a bank transfer order, go to Admin → Orders, find the order, and mark it as Paid to activate their subscription.
Bank Transfer orders do not activate automatically — the admin must confirm payment manually.

Email (SMTP)

WPress Zone sends emails for alert notifications, invoice delivery, and ticket replies. SMTP credentials are set in your .env file, located in the root of your installation (e.g. /var/www/your-app/.env). You can configure SMTP during installation or edit the file directly on the server at any time.

Finding and editing .env

SSH into your server and open the file with any text editor:

nano /var/www/your-app/.env

Locate the MAIL_* block (it is already present — just fill in the values) and save the file. No restart is needed; changes take effect on the next request.

Gmail

Use an App Password (not your regular Gmail password). Generate one at Google Account → Security → 2-Step Verification → App passwords.

MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=you@gmail.com
MAIL_PASSWORD=your_app_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=you@gmail.com
MAIL_FROM_NAME="${APP_NAME}"

Amazon SES

Create SMTP credentials in the AWS Console under SES → SMTP Settings → Create SMTP Credentials. Make sure the sending address or domain is verified in SES first.

MAIL_MAILER=smtp
MAIL_HOST=email-smtp.us-east-1.amazonaws.com
MAIL_PORT=587
MAIL_USERNAME=your_ses_smtp_username
MAIL_PASSWORD=your_ses_smtp_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@yourdomain.com
MAIL_FROM_NAME="${APP_NAME}"

Replace us-east-1 with your SES region (e.g. eu-west-1).

Mailgun

Find your SMTP credentials in the Mailgun dashboard under Sending → Domain Settings → SMTP credentials.

MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=postmaster@mg.yourdomain.com
MAIL_PASSWORD=your_mailgun_smtp_password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@yourdomain.com
MAIL_FROM_NAME="${APP_NAME}"

SendGrid

Create an API key in the SendGrid dashboard with Mail Send permission. Use the literal string apikey as the username.

MAIL_MAILER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=apikey
MAIL_PASSWORD=your_sendgrid_api_key
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@yourdomain.com
MAIL_FROM_NAME="${APP_NAME}"

Disabling email (log only)

To suppress all outgoing email and write messages to the log file instead (useful during testing), set:

MAIL_MAILER=log

You can edit the Terms of Service and Privacy Policy pages directly from the admin panel — no code changes needed.

  1. In the Admin panel, go to Settings → Legal Pages.
  2. Enter your Terms of Service and Privacy Policy content. Plain text and basic HTML are supported.
  3. Click Save Pages.

The pages are publicly accessible at:

https://yourdomain.com/terms
https://yourdomain.com/privacy

These URLs are already linked in the app footer and on the registration/checkout pages.

Plans & Pricing

Go to Admin → Plans → Add Plan, fill in the fields, and save. Plans marked Active show up on the public pricing page immediately.

FieldNotes
NameShown on the pricing page (e.g. Starter, Pro, Agency)
Max SitesSet to 0 for unlimited
Monitoring IntervalMinimum minutes between uptime checks
Log RetentionDays before scan and alert logs are automatically deleted
Alert ChannelsUnchecked channels are hidden from the user's integrations page
ActiveControls visibility on the pricing page
FeaturedHighlights the plan — use for your recommended tier
Changes to plan limits apply to all current subscribers immediately. Lowering Max Sites won't delete existing sites, but the user won't be able to add more until they're within the new limit.

Pricing entries

Each plan can have multiple pricing entries. From the plan's detail page, click Add Pricing and fill in the fields below. This is what the user sees at checkout and what maps to the Stripe price or PayPal plan ID.

FieldNotes
PeriodMonthly, Yearly, Lifetime, or Free — see sections below.
PriceThe amount charged at checkout.
CurrencyMust match the currency configured in your Stripe / PayPal price.

To stop new sign-ups without touching existing subscriptions, uncheck Active on the plan — it drops off the pricing page but current subscribers are unaffected.

Free plans

To offer a free tier, create a plan with the Paid toggle off and add a pricing entry with period set to Free and price 0. Leave the Stripe and PayPal ID fields blank. Every new account is automatically placed on the first free plan found — no checkout is involved and there is no renewal.

Lifetime (LTD) plans

Set the pricing period to Lifetime. The user is charged once and never billed again. On Stripe this is processed as a one-time payment; on PayPal it creates a single-cycle billing plan. Users on a lifetime plan won't see upgrade or renewal prompts anywhere in the UI.

User Management

Search and browse accounts at Admin → Users. Click a user's name to open their profile, where you can see their connected sites, active subscription, and order history.

ActionHowNotes
Suspend / ActivateToggle the status switchBlocks login while preserving all data. Reversible.
DeleteDelete button on the profile pagePermanent — removes the account, sites, logs, and tickets.

If you might need to reinstate someone, suspend rather than delete.

Confirming a bank transfer

Bank transfer orders stay Pending until you approve them manually. Go to Admin → Orders, find the order, and click Mark as Paid — this activates the subscription.

Artisan Commands

CommandDescription
monitor:uptimeDispatch uptime check jobs for all sites
domain:statusCheck domain expiry and SSL certificate for all sites
vulnerabilities:populateSync vulnerability definitions from WPVulnerability.net
plugin-vuln:checkCheck all plugins for known vulnerabilities
theme-vuln:checkCheck all themes for known vulnerabilities
core-vuln:checkCheck WordPress core versions for known CVEs
site-vuln:checkFull vulnerability report per site
logs:delete-oldDelete logs older than each user's plan retention period

FAQ

Uptime checks are not running

Make sure the cron entry is added to your server and the scheduler is running. You can verify with:

php artisan schedule:list

Alerts are not being sent

Check that: (1) the queue worker is running or QUEUE_CONNECTION=sync is set, (2) the alert integration is correctly configured, (3) your plan includes the alert channel you're using.

Stripe payments not working

Verify that the Stripe gateway is enabled in Admin → Gateways and that the Publishable Key, Secret Key, and Webhook Signing Secret are correctly entered there. Stripe credentials are stored in the database, not in .env.

How do I reset the admin password?

php artisan tinker
>>> App\Models\User::where('role', 'admin')->first()->update(['password' => bcrypt('YourNewPassword')])

Site shows "Disconnected" after connecting the plugin

Ensure the API key was saved correctly in the WordPress plugin settings. Also check that your WPress Zone server URL is accessible from the WordPress site (not blocked by firewall).

Can I use this on shared hosting?

Yes. Set QUEUE_CONNECTION=sync in .env and add the cron entry via cPanel. Some features (like real-time alerts) will be slightly delayed but fully functional.

Where do I edit the Terms of Service and Privacy Policy?

Go to Admin → Settings → Legal Pages. Content is stored in the database — no file editing needed. Pages are live at /terms and /privacy.

How do I enable Bank Transfer payments?

Go to Admin → Gateways, enable Bank Transfer, and click Edit to enter your bank account details. These details are shown to customers at checkout and in their invoice email.