Latest update A domain ordered with hosting is checked, priced and registered

Get PNLCS running

PNLCS is a Laravel application. It runs anywhere PHP 8.4, MySQL or MariaDB and a web server are available. To look around first, the live demo is a real installation.

Official image on Docker Hub
docker pull panelica/pnlcs-runtime

Three ways to install

WayBest forTimeGuide
DockerTrying PNLCS, or running it as one containerAbout 5 minutesCommands
Your own serverA VPS or dedicated server without Docker: Ubuntu, Debian, AlmaLinux or Rocky LinuxAbout 30 minutesCommands
Inside a hosting panelA server that already runs Panelica, cPanel or similarAbout 20 minutesGuide

Quick start with Docker

The official image bundles PHP-FPM 8.4, nginx, Node.js 20 and supervisor, and fetches the latest code on first start.

  1. Start the containersReplace changeme with your own passwords first.
  2. Wait 3 to 5 minutesThe first start installs dependencies and builds the frontend.
  3. Open /installThe wizard checks requirements, creates your admin account, then locks itself.
Terminal
$ docker network create pnlcs-net

$ docker run -d --name pnlcs-db --network pnlcs-net \
  -e MYSQL_ROOT_PASSWORD=changeme \
  -e MYSQL_DATABASE=pnlcs -e MYSQL_USER=pnlcs \
  -e MYSQL_PASSWORD=changeme \
  mariadb:11

$ docker run -d --name pnlcs --network pnlcs-net \
  -p 8090:80 \
  -e DB_HOST=pnlcs-db -e DB_DATABASE=pnlcs \
  -e DB_USERNAME=pnlcs -e DB_PASSWORD=changeme \
  -e APP_URL=http://localhost:8090 \
  panelica/pnlcs-runtime:1.4

Install on your own server, without Docker

PNLCS runs as a normal Laravel application on PHP-FPM 8.4, MySQL or MariaDB and Nginx. The commands below cover Ubuntu 24.04, Debian 13 and AlmaLinux 9; Rocky Linux 9 uses the AlmaLinux commands. Replace example.com with your own address.

Full guide
  1. Prepare the server

    PHP 8.4 with its extensions, a database, Nginx, Node.js 20 to build the frontend, and Composer. Skip this if they are already installed.

    Ubuntu 24.04 ships PHP 8.3, so PHP 8.4 comes from the ondrej PPA. Debian 13 has PHP 8.4 itself, ships MariaDB instead of MySQL and has no php8.4-imap package. On AlmaLinux and Rocky, PHP 8.4 comes from the Remi repository.

    Terminal
    $ sudo apt update
    $ sudo apt install -y software-properties-common git unzip curl cron
    $ sudo add-apt-repository -y ppa:ondrej/php
    $ sudo apt update
    $ sudo apt install -y php8.4-fpm php8.4-cli php8.4-mysql php8.4-mbstring \
      php8.4-xml php8.4-curl php8.4-zip php8.4-gd php8.4-bcmath php8.4-intl php8.4-imap
    $ sudo apt install -y mysql-server nginx
    
    $ curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
    $ sudo apt install -y nodejs
    
    $ curl -sS https://getcomposer.org/installer | php
    $ sudo mv composer.phar /usr/local/bin/composer
  2. Install the application

    The PNLCS directory belongs to the web server user, and every composer, artisan and npm command runs as that user. The pn helper does this for you. If root owns the directory, the install wizard and later updates fail.

    Choose one database password and use it in both the CREATE USER and the .env line. The pn helper lasts only for the current shell session; define it again after you log back in.

    Do not run db:seed. The install wizard seeds the database and creates the administrator you choose.

    Terminal
    $ sudo git clone https://github.com/Panelica/pnlcs.git /var/www/pnlcs
    $ sudo chown -R www-data:www-data /var/www/pnlcs
    $ cd /var/www/pnlcs
    $ pn() { sudo -u www-data HOME=/tmp/pnlcs-home COMPOSER_HOME=/tmp/pnlcs-home/composer "$@"; }
    
    $ pn composer install --no-dev --optimize-autoloader --no-interaction
    
    $ sudo mysql -e "CREATE DATABASE pnlcs CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
      CREATE USER 'pnlcs'@'localhost' IDENTIFIED BY 'choose-a-strong-password';
      GRANT ALL PRIVILEGES ON pnlcs.* TO 'pnlcs'@'localhost'; FLUSH PRIVILEGES;"
    
    $ pn cp .env.example .env
    $ pn sed -i 's|^APP_URL=.*|APP_URL=http://example.com|; s|^DB_PASSWORD=.*|DB_PASSWORD=choose-a-strong-password|' .env
    $ sudo chmod 640 .env
    
    $ pn php artisan key:generate
    $ pn php artisan migrate --force
    $ pn npm ci
    $ pn npm run build
    $ pn php artisan storage:link
    $ pn php artisan optimize
  3. Point Nginx at public/

    The document root is the public/ directory, never the project root: the project root holds .env. Remove the default site so the server’s address does not keep showing the Nginx welcome page.

    Apache and Caddy work too, with the same rules: document root public/, PHP through PHP-FPM 8.4, and every request that is not a file rewritten to index.php.

    Terminal
    $ sudo tee /etc/nginx/sites-available/pnlcs > /dev/null <<'EOF'
    server {
        listen 80;
        server_name example.com;
        root /var/www/pnlcs/public;
        index index.php;
        charset utf-8;
        client_max_body_size 64M;
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
        location ~ \.php$ {
            fastcgi_pass unix:/run/php/php8.4-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
            include fastcgi_params;
        }
        location ~ /\.(?!well-known).* { deny all; }
    }
    EOF
    $ sudo ln -s /etc/nginx/sites-available/pnlcs /etc/nginx/sites-enabled/
    $ sudo rm -f /etc/nginx/sites-enabled/default
    $ sudo nginx -t && sudo systemctl reload nginx
  4. Finish in the browser, then schedule and secure

    Open http://example.com/install. The wizard checks the requirements, creates your administrator and then closes itself.

    One cron line for the web server user drives invoices, reminders, suspensions, SSL checks and backups. Queued jobs need no separate worker; the same cron line processes them.

    Terminal
    $ cd /var/www/pnlcs
    $ WEB_USER=www-data   # AlmaLinux, Rocky: apache
    $ (sudo crontab -u $WEB_USER -l 2>/dev/null; echo '* * * * * cd /var/www/pnlcs && php artisan schedule:run >> /dev/null 2>&1') | sudo crontab -u $WEB_USER -
    
    $ sudo apt install -y certbot python3-certbot-nginx   # Ubuntu, Debian
    $ sudo certbot --nginx -d example.com
    $ pn sed -i 's|^APP_URL=http://|APP_URL=https://|' .env
    $ pn php artisan optimize

Requirements

A small installation is comfortable on 2 GB of memory with the database on the same machine.

Full requirements

PHP8.4 or newer
DatabaseMySQL 8.0 or MariaDB 10.6+
Web serverNginx or Apache with PHP-FPM
Node.js18+ (20 LTS recommended), only to build the frontend
Composer2.x
Memory1 GB works for a small install; 2 GB is comfortable
DiskAbout 130 MB for the app; allow at least 2 GB free as data grows

After installing