Deploy on Plesk¶
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
Use PHP 8.4, not 8.3
PNLCS's composer.json states ^8.3, but the shipped composer.lock
resolves to package versions (Symfony 8.x in particular) that require PHP
>=8.4. composer install will fail on PHP 8.3 with errors like
symfony/xyz requires php >=8.4. Set the domain's PHP version to 8.4
in Plesk before installing — this avoids the issue entirely. If 8.4 isn't
available on your server, the alternative is running
composer update --no-dev --optimize-autoloader once to re-resolve an
8.3-compatible lock file, but starting on 8.4 is simpler and is what this
guide assumes from here on.
Option A — Using Plesk's Laravel Toolkit (recommended)¶
- Install the Laravel Toolkit extension in Plesk if it isn't already.
- Go to Laravel in Plesk and click on Install Application
-
Choose a Domain, add the repository
https://github.com/Panelica/pnlcs.git, and click Install Application -
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.
- 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
.deployscript later. - Click Deploy.
- Once deployed, edit the app's environment variables (.env) from the toolkit's dashboard tab (see Environment below).
- Run the Artisan commands from the toolkit's Artisan tab — no SSH needed for this part.
- 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:runcron entry for you.
Node.js version
PNLCS pins a Node version in .node-version (check the file — it may be
ahead of what your distro's package manager ships, e.g. Node 26). 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¶
- 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:
In Plesk: Domain → Hosting Settings → Document Root → pnlcs/public.
- Install PHP extensions. PNLCS needs:
pdo_mysql, mbstring, bcmath, ctype, fileinfo, json, openssl, tokenizer, xml, curl, gd, zip, intl. On Plesk/Debian-based systems these come asplesk-php84-<extension>packages — check what's active first:
- Install Composer dependencies using the Plesk PHP binary explicitly, so you don't accidentally use a different system PHP:
- Install Node and build assets. If the version in
.node-versionisn't available via your distro's package manager (common for very recent versions), 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 "$(cat .node-version)"
npm ci
npm run build
-
Configure
.env— see Environment below. -
Run the Artisan commands — see below.
-
Fix ownership/permissions. Anything run as
rootduring setup (e.g. an interactivesusession that didn't fully take, or a manualchownthat Plesk's ACL model disagrees with) can leave files owned incorrectly for the subscription's system user. Rather than hand-craftingchown/chmod, let Plesk reconcile it against its own conventions:
- Queue worker. Plesk doesn't run long-lived processes on its own — 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
- Scheduler cron. Add to the subscription's crontab (Plesk → Scheduled
Tasks, or
crontab -u your_subscription_system_user -e):
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 --seed
php artisan storage:link
migrate --seed creates the default administrator account
(admin / admin123). Log in and change this immediately — see
First Login.
Verify¶
- Visit
https://app.example.com/admin/loginand confirm the login page loads (not a 500 or blank page — if so, checkstorage/logs/laravel.log). - Confirm SSL is active (Plesk → SSL/TLS Certificates → Let's Encrypt) with HTTP→HTTPS redirect enabled.
- Confirm the queue worker and scheduler are actually running — see Scheduled Commands.
- Continue with the Setup Checklist.