Skip to content

Deploy on Plesk

Updated

PNLCS runs well on a Plesk server, either through Plesk's Laravel Toolkit extension (recommended — handles most of the build steps for you) or fully manually over SSH. This guide covers both paths and the gotchas that are easy to miss on Plesk specifically.

Prerequisites

  • A Plesk subscription/domain already created for the app (e.g. app.example.com)
  • PHP 8.4 required in Plesk (check Domain → PHP Settings) — see note below
  • MySQL 8 (or MariaDB 10.11+)
  • Root or SSH access to the server for the manual steps below

PHP 8.4 is required

PNLCS's composer.json requires PHP ^8.4 and the install wizard refuses anything older. Set the domain's PHP version to 8.4 in Plesk (Domain → PHP Settings) before installing.

  1. Install the Laravel Toolkit extension in Plesk if it isn't already.
  2. Go to Laravel in Plesk and click on Install Application image

image

  1. Choose a Domain, add the repository https://github.com/Panelica/pnlcs.git, and click Install Application image

  2. Set Deployment mode to Manual (safer for a first install — you control exactly when it deploys) or Automatic if you want it to redeploy on every push.

  3. Under Deployment steps, leave the defaults checked: fetch source, install Composer dependencies, install npm dependencies, disable maintenance mode. The "Run deployment script" step is only needed if you add a custom .deploy script later.
  4. Click Deploy.
  5. Once deployed, edit the app's environment variables (.env) from the toolkit's dashboard tab (see Environment below).
  6. Run the Artisan commands from the toolkit's Artisan tab — no SSH needed for this part.
  7. Enable the Scheduled Tasks and Queue toggles on the toolkit dashboard. This replaces the manual cron/systemd steps in Option B entirely — Plesk manages the worker process and the schedule:run cron entry for you.

Node.js version

The frontend build needs Node.js 20.19+ or 22.12+ (Vite 8). The Laravel Toolkit's own Node.js tab lets you pick a Node version for the build step independently of what's installed system-wide, so this usually isn't a manual concern under Option A.

Option B — Manual deployment over SSH

  1. Clone outside the web root, then point the document root at public/ rather than the repo root — Laravel apps must never serve their own project root:
cd /var/www/vhosts/example.com
git clone https://github.com/Panelica/pnlcs.git pnlcs

In Plesk: Domain → Hosting Settings → Document Root → pnlcs/public.

  1. Install PHP extensions. The install wizard checks for: bcmath, curl, dom, fileinfo, gd, intl, mbstring, openssl, pdo_mysql, tokenizer, xml, zip. On Plesk/Debian-based systems these come as plesk-php84-<extension> packages — check what's active first:
/opt/plesk/php/8.4/bin/php -m | sort
  1. Install Composer dependencies using the Plesk PHP binary explicitly, so you don't accidentally use a different system PHP:
/opt/plesk/php/8.4/bin/php $(which composer) install --no-dev --optimize-autoloader
  1. Install Node and build assets. You need Node.js 20.19+ or 22.12+. If your distro's package manager ships an older one, use nvm rather than fighting distro packages:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
nvm install 22
npm ci
npm run build
  1. Configure .env — see Environment below.

  2. Run the Artisan commands — see below.

  3. Fix ownership/permissions. Anything run as root during setup (e.g. an interactive su session that didn't fully take, or a manual chown that Plesk's ACL model disagrees with) can leave files owned incorrectly for the subscription's system user. Rather than hand-crafting chown/chmod, let Plesk reconcile it against its own conventions:

plesk repair fs example.com -y
  1. Queue worker (optional). The scheduler in step 9 already starts a queue:work run every minute, so with QUEUE_CONNECTION=database queued jobs wait at most a minute without any extra process. Add a permanent worker only if you want them to run instantly. Plesk doesn't run long-lived processes on its own, so create a systemd unit:
# /etc/systemd/system/pnlcs-queue.service
[Unit]
Description=PNLCS Queue Worker
After=network.target mysql.service

[Service]
User=your_subscription_system_user
WorkingDirectory=/var/www/vhosts/example.com/pnlcs
ExecStart=/opt/plesk/php/8.4/bin/php artisan queue:work --tries=3 --timeout=90
Restart=always

[Install]
WantedBy=multi-user.target
systemctl enable --now pnlcs-queue
  1. Scheduler cron. Add to the subscription's crontab (Plesk → Scheduled Tasks, or crontab -u your_subscription_system_user -e):
* * * * * /opt/plesk/php/8.4/bin/php /var/www/vhosts/example.com/pnlcs/artisan schedule:run >> /dev/null 2>&1

Environment

Set at minimum:

APP_NAME=PNLCS
APP_ENV=production
APP_DEBUG=false
APP_URL=https://app.example.com

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_db_name
DB_USERNAME=your_db_user
DB_PASSWORD=your_db_password

QUEUE_CONNECTION=database

Leave APP_KEY blank if you haven't generated one yet — the Artisan step below handles it. If you're deploying through the Laravel Toolkit, it may already have generated a key for you during the first deploy; check before overwriting it.

Artisan commands

Run these once, in order, after dependencies are installed and .env is set:

php artisan config:clear
php artisan key:generate   # skip if APP_KEY is already set
php artisan migrate --force
php artisan storage:link

Then open https://app.example.com/install. The install wizard seeds the starting data and creates the administrator with the username and password you choose. Do not add --seed to the migrate line: seeding by hand creates the administrator admin with a random password, printed once in the command's output (or PNLCS_ADMIN_PASSWORD, if you set it), and the wizard, seeing an administrator, closes itself. Seed by hand only for a headless install with no browser step, and change that password first — see First Login.

Verify

  1. Visit https://app.example.com/admin/login and confirm the login page loads (not a 500 or blank page — if so, check storage/logs/laravel.log).
  2. Confirm SSL is active (Plesk → SSL/TLS Certificates → Let's Encrypt) with HTTP→HTTPS redirect enabled.
  3. Confirm the queue worker and scheduler are actually running — see Scheduled Commands.
  4. Continue with the Setup Checklist.