menu_book Navigation menu

Installation & Hosting

Local

Configure Virtual Hosts for Local Development

For an optimal development experience that perfectly simulates a production environment, we strongly recommend configuring Virtual Hosts.

This will allow you to access your sites via clean, realistic URLs (e.g., http://my_site_1.local).

The process is done in 3 simple steps and takes only 5 minutes.

Prerequisites

  • A local development environment like XAMPP (Windows/Linux) or MAMP (macOS).
  • Administrator rights on your machine to modify configuration files.

Step 1: Modify your hosts file

The hosts file is your computer's address book. We will tell it that your test site domains point to your local machine (127.0.0.1).

info
Instructions for Windows
  1. Open Notepad as an administrator (right-click icon > "Run as administrator").
  2. In Notepad, go to "File" → Open, and open the file: C:\\Windows\\System32\\drivers\\etc\\hosts (remember to select "All files (*.*)" to display the hosts file).
  3. At the end of the file, add a line for each domain:
BASH
# Pragma CMS Local Development Sites
127.0.0.1 platform.pragma-cms.local
127.0.0.1 mon-site-1.local
127.0.0.1 mon-site-2.local
  1. Save and close the file.
info
Instructions for macOS (MAMP)
  1. Open the Terminal application.
  2. Type the following command to open the hosts file with administrator rights and press Enter: sudo nano /etc/hosts
  3. Enter your macOS session password when prompted.
  4. At the end of the file, add a line for each domain:
BASH
# Pragma CMS Local Development Sites
127.0.0.1 platform.pragma-cms.local
127.0.0.1 my-site-1.local
127.0.0.1 my-site-2.local
  1. To save, press Ctrl + O, then Enter. To quit, press Ctrl + X.

Step 2: Configure Virtual Hosts in Apache

Now, we will tell Apache how to handle requests for these new domains.

info
Instructions for Windows (XAMPP)
  1. In the XAMPP control panel, click Config (for Apache) > httpd.conf.
  2. In the file, search for the line Include conf/extra/httpd-vhosts.conf.
  3. Remove the # to enable the line, then save and close the file.
  4. Open the httpd-vhosts.conf file: C:\xampp\apache\conf\extra\httpd-vhosts.conf
  5. Add the following block, replacing "C:/xampp/htdocs/pragma-cms" with the actual path to your project:

    💡Important: All domains must point to the same /public folder of Pragma CMS.
BASH
# Virtual Host for the platform

    DocumentRoot "C:/xampp/htdocs/pragma-cms/public"
    ServerName platform.pragma-cms.local
    
        AllowOverride All
        Require all granted
    


# Virtual Host for my-site-1.local

    DocumentRoot "C:/xampp/htdocs/pragma-cms/public"
    ServerName mon-site-1.local
    
        AllowOverride All
        Require all granted
    
  1. Save and close the file.
info
 Note: If you use MAMP PRO, you can create virtual hosts directly from the GUI, which is much simpler.
  1. In the MAMP interface, go to the menu File > Edit Template > Apache > httpd.conf.
  2. In the file, search for the line #Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf.
  3. Remove the # to enable the line, then save and close the file.
  4. Go back to the menu File > Edit Template > Apache > extra/httpd-vhosts.conf.
  5. Add the following block, replacing /Applications/MAMP/htdocs/pragma-cms with the actual path to your project:

    💡 Important: All domains must point to the same /public folder of Pragma CMS.
BASH
# Virtual Host for the platform

    DocumentRoot "/Applications/MAMP/htdocs/pragma-cms/public"
    ServerName platform.pragma-cms.local
    
        AllowOverride All
        Require all granted
    


# Virtual Host for my-site-1.local

    DocumentRoot "/Applications/MAMP/htdocs/pragma-cms/public"
    ServerName mon-site-1.local
    
        AllowOverride All
        Require all granted
    
  1. Save and close the file.

Step 3: Enable Error Display

For a local environment, it is often necessary to enable display_errors=On in php.ini to see errors in the browser.

Step 4: Restart Apache

For the changes to take effect, restart the servers from the XAMPP or MAMP control panel.

  1. Click Stop Servers (or Stop next to Apache).
  2. Wait for a complete stop.
  3. Click Start Servers (or Start).

You're all set!

You can now open your browser and visit your sites directly:

  • http://platform.pragma-cms.local
  • http://my-site-1.local
  • http://my-site-2.local

Your local installation now behaves exactly like a production server.

Production

This guide details the steps to deploy Pragma CMS Platform on a dedicated server/VPS. This architecture is designed for performance, security, and multi-site management (SaaS).

1. Rent the Server (The VPS)

Get a VPS from a reputable provider (OVH, Hetzner, DigitalOcean, etc.).

  • Recommended config to start: 2 vCPU, 4GB RAM (to comfortably run PHP/MySQL).
  • OS: Choose an Operating System (OS).
  • For professional hosting, we recommend using a Linux distribution. You have two main choices:
    • Ubuntu LTS (Recommended for beginners):
      Pros: Very popular, extensive documentation, easy access to recent PHP versions, simplified configuration.
      Cons: Slightly heavier than Debian (includes more tools by default).
    • Debian (The purist's choice):
      Pros: Legendary stability, extremely lightweight ("Bare metal"), 100% open source.
      Cons: Slower update cycle, sometimes requires more manual configuration.
Note: This guide will use commands for Ubuntu 22.04 / 24.04 LTS, but they are 99% compatible with Debian.

2. Securing the VPS

  • Create a user (with your name) if not already done (never stay as root)Working as root is dangerous. If a script or a hacker gets in, they have full rights. We will create an administrator user.
    • Connect as root one last time:
BASH
ssh root@YOUR_IP
  • Create a new user (replace my_pseudo with your desired name):
BASH
adduser my_pseudo
# (Choose a strong password, leave the rest blank by pressing Enter)
  • Give them sudo rights:
BASH
usermod -aGsudo my_pseudo
  • SSH Keys (The Unpickable Lock)
    Passwords can be guessed (brute force), but cryptographic SSH keys cannot.
    • On your personal PC (not the server), open a terminal (PowerShell or CMD on Windows, Terminal on Mac/Linux).
    • Generate a key pair (if you don't already have one):
BASH
ssh-keygen -t ed25519 -C"admin@pragma-cms"
# Press Enter for everything or set a passphrase for added security
  • Send the public key to your server:
BASH
# On Linux/Mac:
ssh-copy-id my_pseudo@YOUR_VPS_IP

# On Windows (if ssh-copy-id does not exist):
type$env:USERPROFILE\.ssh\id_ed25519.pub | ssh my_pseudo@YOUR_VPS_IP"mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
  • Test immediately:
BASH
ssh my_pseudo@YOUR_VPS_IP

If the connection is made without asking for a password (or only the key's passphrase), you've succeeded.

warning
Important
Never close the active SSH session until you have tested the connection with the new user. This precaution allows you to correct any SSH or firewall issues without losing access to the server.
support
Rescue (in case of trouble)
If you get locked out (misconfigured firewall, unreachable SSH port, lost SSH key), for OVH, go to your OVH customer area → VPS section. A “KVM” or “Emergency Console” button is available. This console simulates physical access to the server (screen + keyboard), even if SSH is no longer working. The keyboard layout may be QWERTY, so remember to switch it to AZERTY once connected (see your web hosting provider’s documentation). You will be able to log in with your user account and fix the configuration (SSH, firewall, users, etc.).   

3. Installation Method

Automatic Installation (Recommended)

rocket_launch
Automatic Server Setup
This script installs and configures the full server stack: web server (Caddy), PHP, database (MariaDB), security, file structure, and scheduled tasks.
  1. Download the script from your computer to the VPS:
BASH
scp -P 22 /chemin/local/to/scripts/setup/install_server.sh my_pseudo@YOUR_IP:~
  1. Launch the installation on the VPS:
BASH
sudo bash install_server.sh
  1. Follow the on-screen instructions.
  2. Once finished, continue to step 4 (File Deployment).

Manual Installation (Advanced)

info
Step-by-step installation
For advanced users who want full control over the setup. If you used the automatic script, do not follow the steps below. Each section describes what the script does internally.   
1. Advanced Security (SSH & Firewall)
  • Lock Down SSH (Change the lock)
    Now that you have your key, let's forbid passwords and close the root door.
    • On the server (connected as my_pseudo), edit the SSH configuration:
BASH
sudo nano /etc/ssh/sshd_config
  • Modify or add the following lines:
BASH
# 1. Change the port (security by obscurity, reduces 99% of bot logs)
Port 54321  # Choose a number between 1024 and 65535 and note it down!

# 2. Forbid direct root login
PermitRootLogin no

# 3. Forbid passwords (SSH key mandatory)
PasswordAuthentication no
PermitEmptyPasswords no

# 4. Limit to authorized users
AllowUsers my_pseudo
  • Save (Ctrl+X, Y, Enter).
    ⚠️ DO NOT RESTART SSH YET. We must configure the firewall first.
  • Preventive Step: Avoid Configuration Conflicts (Cloud-init & Systemd)
    Before going further, let's check that nothing will prevent the port change. This is a frequent problem on modern VPS providers (OVH, AWS).
    1. Check for conflicting configuration files
      Some providers force port 22 via additional files. If they exist, they will overwrite your change.
BASH
ls /etc/ssh/sshd_config.d/
 If you see .conf files (like 50-cloud-init.conf), delete them:  
BASH
sudo rm /etc/ssh/sshd_config.d/*.conf
  1.  Check Socket activation (Ubuntu 22.04+)
    On recent versions, SSH can be managed by a systemd socket, which ignores your port configuration. Let's disable it preventively to give control back to the classic SSH service.
BASH
# Check if the socket is active
systemctl is-active ssh.socket
 If the answer is active, run these commands to disable it:  
BASH
sudo systemctl stop ssh.socket
sudo systemctl disable ssh.socket
  • Firewall (UFW – The Bouncer)
    UFW will close all ports except for the Web and your new SSH port.
BASH
# 1. Install UFW (often already present)
sudo apt install ufw -y

# 2. Default rules: block all incoming, allow all outgoing
sudo ufw default deny incoming
sudo ufw default allow outgoing

# 3. Allow your new SSH port
sudo ufw allow 54321/tcp

# 4. Allow Web (80 and 443)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# 5. Enable the firewall
sudo ufw enable
# (Answer 'y' to the confirmation)
  • Restart SSH after configuration:
BASH
sudo systemctl restart ssh
  • Critical test: open a new terminal and try to connect:
BASH
ssh -p 54321 my_pseudo@YOUR_VPS_IP
 ⚠️  Important : Never close the active SSH session until you have tested the new connection. Always open a new terminal to verify you can reconnect with the new user and port before closing the old session.   
If that works, well done. If not, do not close your current SSH session. Use it to fix the configuration or proceed to the recovery procedure described in the next section “Troubleshooting: SSH lockout recovery”.  
  • Fail2Ban (The Watchdog)
    Even with a changed port, bots will try to scan your server. Fail2Ban automatically bans IPs that make too many errors.
BASH
# 1. Installation
sudo apt install fail2ban -y

# 2. Local configuration
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local
  • In this file, search for the [sshd] section (often around line 280) and modify the port:
BASH
[sshd]
enabled = true
port    = 54321 # Your SSH port here
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3 ; To be added generally
bantime = 1h ; To be added generally
findtime = 10m
  • Save (press Ctrl+X to exit, then Y to confirm, followed by Enter) and restart:
BASH
sudo systemctl restart fail2ban
  • Automatic Updates (Passive Security)
    For a commercial CMS, you don't want to miss a critical Linux vulnerability.
BASH
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades
# Choose "Yes" (Enter)
  • Final clean-up (Optional): Once you’ve logged in with your new username my_pseudo, you can delete the default user for added security: sudo userdel -r ubuntu.
🆘 Troubleshooting: SSH lockout recovery (KVM / systemd / firewall)
If after changing the port and restarting the service you get a Connection refused or Timeout error when attempting to connect (ssh -p 54321 ...), it means you may have effectively “locked yourself out”. Don’t worry — here is the procedure to regain access via the recovery console.   
  1. Access the KVM Console (Virtual Screen)
    Log in to your hosting provider dashboard (e.g., OVH) and launch the KVM (or VNC) console. This is a window that simulates the physical screen of the server.
  2. Fix Keyboard Layout (QWERTY vs AZERTY)
    By default, the KVM console is often configured in English (QWERTY).
    • Log in with your user (ubuntu or your new user).
    • Tip: If your password contains an “a”, type “q”. If “z”, type “w”. “m” is located where “,” is on AZERTY keyboards.
Once logged in, switch the keyboard layout to French for easier use:  
BASH
sudo dpkg-reconfigure keyboard-configuration
  1. Keyboard model: Select "Generic 105-key PC"
  2. Country: Select "Other", then "French"
  3. Layout: Select "French (default)"
  4. Leave the other options as default
 Apply the changes:  
BASH
sudo systemctl restart keyboard-setup
  1. Diagnose the issue
    Check which port SSH is actually listening on:
BASH
sudo ss -ltnp | grep ssh
  • If you see 0.0.0.0:22: the server is still listening on port 22 (your change was not applied). Follow Solution A, then B, then C.
  • If you see 0.0.0.0:54321: SSH is correctly listening on the new port; the issue is likely the firewall. Proceed to the firewall section below.
 Solution A: Check the main configuration  
 Make sure the # has been removed from the Port line.  
BASH
sudo nano /etc/ssh/sshd_config
# Ensure the line is: Port 54321 (not #Port 54321)
Solution B: Remove conflicting configuration files (common OVH/Cloud case)
On modern cloud images, default configuration files may force port 22 and override your settings. These can override your configuration and should be removed.
Check if they exist:   
BASH
ls /etc/ssh/sshd_config.d/
If you see files such as 50-cloud-init.conf or 60-cloudimg-settings.conf, remove them:
BASH
sudo rm /etc/ssh/sshd_config.d/*.conf
sudo systemctl restart ssh
Verify again with sudo ss -ltnp | grep ssh. If it shows :54321, try connecting again from your local machine.  
Solution C: Disable the systemd socket (recent Ubuntu systems)  
If port 22 persists, systemd is handling SSH via a socket instead of the SSH service itself. You must disable it to restore control to SSH.  
BASH
# Stop the socket listener on port 22
sudo systemctl stop ssh.socket
# Prevent it from starting at boot
sudo systemctl disable ssh.socket
# Restart SSH
sudo systemctl restart ssh
4. Check the firewall (UFW)
If SSH is listening on the correct port but connections still fail, open the port in the firewall:  
BASH
sudo ufw allow 54321/tcp
sudo ufw reloaddrag_indicatorformat_indent_increase× You should now be able to connect from your local terminal.  
 You should now be able to connect from your local terminal.  
2. Stack Installation (Software)
Connect to your VPS via SSH (ssh root@your-ip) and run the following commands.  
 💡 To avoid adding sudo every time, type sudo -i.   
  • Step A: System Update
BASH
apt update && apt upgrade -y
 Base Utilities:  
BASH
apt install -y curl zip unzip git software-properties-common
  • Step B: Web Server Installation (Choose Caddy, Nginx, or Apache)
If you choose Caddy (recommended), install it using the official commands (this requires adding the Caddy repository, see caddyserver.com or the steps below). 
Caddy is not available in the default package repositories, so it must be added manually (official commands):   
BASH
# Add Caddy security keys
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list

# Installation
apt update
apt install caddy -y
Test: Enter your VPS's IP address into your browser. You should see a page that says ‘Caddy works!’  
  • Step C: Installing PHP 8.4 (or higher)
Pragma CMS requires specific extensions to function (image processing, zip, databases).  
BASH
# Update package lists
apt update

# Install PHP and required dependencies
apt install -y php-fpm php-mysql php-curl php-gd php-intl php-mbstring php-xml php-zip php-imagick ghostscript
  • Step D: MariaDB Installation (Database)
BASH
apt install mariadb-server -y
mysql_secure_installation # Answer Y to everything to secure
3. PHP Optimization (OPcache)
To ensure the CMS is fast while allowing real-time file modifications (via SSH/VS Code), configure OPcache as follows:  
  1. Open PHP configuration:
BASH
# Adjust the version number (8.4 or later) depending on what you have installed
sudo nano /etc/php/8.4/fpm/conf.d/99-pragma.ini
  1. Add the content:
BASH
; ============================
; Pragma OPcache Configuration
; ============================

[opcache]
; Enable OPcache
opcache.enable=1

; Memory allocation
opcache.memory_consumption=256 ; Increased to 256MB (comfortable for a 8GB VPS)
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000  ; Increased to handle core system + client sites

; BALANCED CONFIGURATION (PERFORMANCE + FLEXIBILITY)
opcache.validate_timestamps=1        ; Tells PHP to check if files have changed
opcache.revalidate_freq=0            ; Revalidate on every request (instant updates)
opcache.save_comments=1 ; Keep comments (required for some CMS internal logic)
  1. Save and exit: Ctrl+X, Y, Enter.
  2. Apply changes:
BASH
sudo systemctl restart php8.4-fpm
4. Database Configuration
You must create a database for the Platform and a "Master" user who will have the right to create other databases (for your future client sites). 
To ensure the security of your tests, we will create two separate databases: one for Production and one for Staging (Tests). 
Connect to MySQL:   
BASH
sudo mysql
Once you’re at the MariaDB prompt (MariaDB [(none)]>), type the following:  
BASH
-- PRODUCTION DATABASE
CREATE DATABASE pragma_cms_platform CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- STAGING DATABASE
CREATE DATABASE pragma_cms_platform_staging CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- Create the ‘Master’ user (who will be able to create customer databases)
-- Replace “MySuperPassword” with a real, strong password!
CREATE USER 'pragma_master'@'localhost' IDENTIFIED BY 'MySuperPassword';

-- Give him full access to ALL databases (as he needs to create websites)
GRANT ALL PRIVILEGES ON *.* TO 'pragma_master'@'localhost' WITH GRANT OPTION;

FLUSH PRIVILEGES;
EXIT;
5. File Architecture, Permissions, and Deployment
This step prepares the server to host the Pragma CMS Platform. We will create the directory structure and set up robust access controls (ACLs) to prevent any conflicts between your SSH user and the web server. 
Run these commands one by one on your VPS:   
  • Installing the ACL tool
BASH
# Installing the ACL (Access Control Lists) tool
# Essential for fine-grained permission management without compromising security
sudo apt install acl -y
  • Creating directories for the “pragma-cms” production environment
BASH
# 1. Creating the directory structure (the folders currently belong to root)
sudo mkdir -p /var/www/pragma-cms/public
sudo mkdir -p /var/www/pragma-cms/public/assets/cms-core
sudo mkdir -p /var/www/pragma-cms/cms-versions
sudo mkdir -p /var/www/pragma-cms/sites
sudo mkdir -p /var/www/pragma-cms/storage/tmp
sudo mkdir -p /var/www/pragma-cms/storage/cache
sudo mkdir -p /var/www/pragma-cms/storage/logs
sudo mkdir -p /var/www/pragma-cms/scripts/cli
sudo mkdir -p /var/www/pragma-cms/scripts/cron
sudo mkdir -p /var/www/pragma-cms/scripts/setup

# 2. Basic standard configuration
# Set the web server’s ownership to the www-data group and apply standard permissions (755)
sudo chown -R www-data:www-data /var/www/pragma-cms
sudo chmod -R 755 /var/www/pragma-cms

# 3. APPLYING EXTENDED PERMISSIONS (ACL)
# This step is crucial: it ensures that YOU (your SSH user: replace $USER here) 
# and PHP (www-data) will always be able to read and write files, 
# regardless of who created them.

# A. Apply to existing folders
sudo setfacl -R -m u:www-data:rwx /var/www/pragma-cms
sudo setfacl -R -m u:$USER:rwx /var/www/pragma-cms

# B. Apply default permissions (-d)
# This forces all FUTURE files created (by PHP or VS Code) 
# to automatically inherit these permissions, even if PHP creates a directory with 0755 permissions.
sudo setfacl -R -d -m u:www-data:rwx /var/www/pragma-cms
sudo setfacl -R -d -m u:$USER:rwx /var/www/pragma-cms
  • Creating directories for the staging “pragma-cms-staging”
BASH
# 1. Creating the directory structure (folders are initially owned by root)
sudo mkdir -p /var/www/pragma-cms-staging/public
sudo mkdir -p /var/www/pragma-cms-staging/public/assets/cms-core
sudo mkdir -p /var/www/pragma-cms-staging/cms-versions
sudo mkdir -p /var/www/pragma-cms-staging/sites
sudo mkdir -p /var/www/pragma-cms-staging/storage/tmp
sudo mkdir -p /var/www/pragma-cms-staging/storage/cache
sudo mkdir -p /var/www/pragma-cms-staging/storage/logs
sudo mkdir -p /var/www/pragma-cms-staging/scripts/cli
sudo mkdir -p /var/www/pragma-cms-staging/scripts/cron
sudo mkdir -p /var/www/pragma-cms-staging/scripts/setup

# 2. Basic standard configuration
# Set ownership to the web server group (www-data) and apply standard permissions (755)
sudo chown -R www-data:www-data /var/www/pragma-cms-staging
sudo chmod -R 755 /var/www/pragma-cms-staging

# 3. APPLY EXTENDED PERMISSIONS (ACL)
# This step is critical: it ensures that YOU (your SSH user: replace $USER) 
# and PHP (www-data) can always read and write files, 
# regardless of who created them.

# A. Apply to existing directories
sudo setfacl -R -m u:www-data:rwx /var/www/pragma-cms-staging
sudo setfacl -R -m u:$USER:rwx /var/www/pragma-cms-staging

# B. Apply default inheritance (-d)
# This ensures all FUTURE files created (by PHP or VS Code)
# automatically inherit these permissions, even if PHP creates them with 0755.
sudo setfacl -R -d -m u:www-data:rwx /var/www/pragma-cms-staging
sudo setfacl -R -d -m u:$USER:rwx /var/www/pragma-cms-staging
6. Web Server Configuration
For Pragma CMS to work, your web server must redirect all traffic to the public/ folder. We will proceed in two stages: first, a test configuration to check that everything works via your IP address, followed by the final production configuration.  
  • Step A: Create a test file
    Before configuring the server, let's create a small file to verify that PHP is working correctly.

    You can create this file in two ways:
    • Via VS Code:
      In the left file explorer, right-click the public folder → New File, name it test.php, and paste the content below.
    • Via terminal:
BASH
echo"" > /var/www/pragma-cms/public/test.php
  • Step B: Temporary configuration (IP test)
    We will configure Caddy (recommended) to serve the site using your server IP address, without HTTPS for now.
    1. Open the Caddy configuration file /etc/caddy/Caddyfile (via VS Code or sudo nano /etc/caddy/Caddyfile).
    2. Replace its content with the following (use your real IP):
BASH
# Replace X.X.X.X with your VPS IP
http://X.X.X.X {
    root * /var/www/pragma-cms/public
    encode gzip
    file_server
    
    # PHP 8.4
    php_fastcgi unix//run/php/php8.4-fpm.sock
}
  1. Apply the configuration:
BASH
sudo systemctl reload caddy
  1. Test it! Open your browser and go to: http://VOTRE_IP/test.php.
    • ✅ Success: If you see the purple PHP info page, your server is working correctly.
    • ❌ Error 502: Caddy cannot reach PHP. Ensure PHP 8.4 FPM is installed and running.
  • Step C: Final configuration (Production & HTTPS)
    Now that the server works, we move to the production setup that handles domains and automatic SSL.
    1. Remove the test file
BASH
rm /var/www/pragma-cms/public/test.php
  1. Generate a basic auth hash for staging access
    Generate a password hash using:
BASH
sudo caddy hash-password
Save the generated hash securely. 
This will be used to protect staging environments like:   
BASH
staging-site-test.mon-site.com
Make sure to create the corresponding DNS record.  
  1. Replace the entire Caddy configuration
    Replace /etc/caddy/Caddyfile with the following:
BASH
# =========================================================================
# == SNIPPETS (Reusable configurations)
# =========================================================================

# Common CMS configuration (Security, PHP, Assets)
(cms_common) {
    # 1. Web root (argument {args[0]} passed when importing)
    root * {args[0]}/public

    # 2. ASSET / MEDIA / UPLOAD / THEME HANDLING (core logic)
    # If a file is requested in /assets or /media and does NOT exist,
    # redirect to asset handler script
    @missing_assets {
        path /assets/* /media/* /uploads/* /themes/*
        not file {path}
    }
    rewrite @missing_assets /assets/serve-site-assets.php?{query}

    # 3. PHP FastCGI (Script execution) – Make sure it’s compatible with your version of PHP!
    php_fastcgi unix//run/php/php8.4-fpm.sock

    # 4. Front Controller (main routing)
    # If the file does not exist, everything is redirected to index.php
    try_files {path} {path}/ /index.php?{query}

    # 5. Compression and Static File Server
    encode gzip zstd
    file_server
}

# =========================================================================
# == SERVER BLOCKS
# =========================================================================

# 1. Global SSL (on-demand TLS)
{
    on_demand_tls {
        ask http://localhost:8080/check-domain
    }
}

# 2. Internal server for check-domain (inaccessible from outside)
# This server is only accessible by Caddy itself (localhost)
# It is used solely to respond to the ‘ask’
http://localhost:8080 {
    root * /var/www/pragma-cms/public

    # We use php_fastcgi just for this specific route
    route /check-domain {
        php_fastcgi unix//run/php/php8.4-fpm.sock
    }
}

# 3. PROD PLATFORM (Super Admin / Main Dashboard)
# Caddy will manage this certificate automatically and ‘for free’ (without involving PHP)
NOM_DE_DOMAINE_DE_LA_PLATEFORME {
    # Import the shared configuration with the PROD path
    import cms_common /var/www/pragma-cms

    log {
        output file /var/log/caddy/platform-access.log
    }
}

# 4. STAGING (Platform & Test client sites)
# Replace $USER with your username and MY_HASH with your generated hash
staging.mon-site.com,
staging-site-test.mon-site.com {
    # Password protection
    basic_auth {
        $user MY_HASH
    }

    # Import the shared configuration using the STAGING path
    import cms_common /var/www/pragma-cms-staging

    # Google anti-indexing
    header X-Robots-Tag "noindex, nofollow"

    log {
        output file /var/log/caddy/staging-access.log
    }
}

# 5. CLIENT PRODUCTION SITES (catch-all HTTPS)
https:// {
    # On-demand SSL activation
    tls {
        on_demand
    }

    # Import the shared configuration using the PROD path
    import cms_common /var/www/pragma-cms

    log {
        output file /var/log/caddy/pragma-access.log
    }
}
  1. Apply the final configuration:
BASH
sudo systemctl reload caddy
  ℹ️  Alternatives (If you are not using Caddy)
 ⚠️ Note:
Apache and Nginx configurations below do not support automatic SSL generation for unknown domains. You must configure Certbot manually or use an automation script (e.g. Lua/OpenResty) if not using Caddy.   
If you prefer to use Apache or Nginx, here are the equivalent configurations for the final step.  
  • Option A: Apache (standard)
    Pragma CMS includes a pre-configured .htaccess file in the public/ folder. Ensure mod_rewrite is enabled.

    VirtualHost Configuration:
BASH

    ServerName platform.pragma-cms.com
    ServerAlias *.platform.pragma-cms.com
    
    # IMPORTANT NOTE: We are pointing directly to /public
    # The .htaccess file in the project root directory is therefore ignored.
    # Only the .htaccess file located WITHIN /public will be read.
    DocumentRoot /var/www/pragma-cms/public

    
        Options -Indexes +FollowSymLinks
        
        # Enable the .htaccess file in /public (essential for routing and URL rewriting)
        AllowOverride All
        
        Require all granted
    

    ErrorLog ${APACHE_LOG_DIR}/pragma_error.log
    CustomLog ${APACHE_LOG_DIR}/pragma_access.log combined
  • Option B: Nginx (performance)
    Nginx does not support .htaccess. Use the following configuration in /etc/nginx/sites-available/pragma-cms:
BASH
server {
    listen 80;
    server_name platform.pragma-cms.com *.platform.pragma-cms.com;
    
    root /var/www/pragma-cms/public;
    index index.php;

    access_log /var/log/nginx/pragma_access.log;
    error_log /var/log/nginx/pragma_error.log;

    # --- ASSET ROUTING ---
    # Equivalent to @missing_assets in Caddy.
    # If the file does not exist in /public/assets or /public/media,
    # control is passed to serve-site-assets.php
    location ~ ^/(assets|media|uploads|themes)/ {
        try_files $uri /assets/serve-site-assets.php$is_args$args;
    }

    # Main router (Front Controller)
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # PHP execution
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Hidden file security
    location ~ /\.(?!well-known).* {
        deny all;
    }
}

4. Deploying CMS Files to the VPS

Now that the server is ready (via the script or manual setup), you need to upload the Pragma CMS installation files to your server.

You should have downloaded a .zip archive (the installation package) from your Pragma customer area.

  • Via SFTP:
    • Use a tool such as FileZilla or Cyberduck.
    • Connect to your VPS (IP, username, password/key).
    • Navigate to /var/www/pragma-cms/.
    • Upload the contents of the public folder from the archive into the server’s public/ directory.
    • Upload the cms-versions folder from the archive into /var/www/pragma-cms/.
  • Via VS Code (Remote - SSH):
    • You can directly upload and edit files on the server using VS Code.

Final directory structure check:
Your server should look like this:

  • 📁 /var/www/pragma-cms/ 
    • 📁 cms-versions/ (Core system files, e.g. v1.0.0. Do not modify)
    • 📁 public/ (Contains index.phpcheck-domain.php (Caddy only), and assets. This is the web root)
    • 📁 sites/ (Empty for now, will contain your future sites)
Important: 
Never modify files inside cms-versions/. This folder is managed automatically by the update system. Any changes will be overwritten during the next update.
lightbulb
Configuring VS Code for Remote Development (SSH)
This method allows you to edit files on your VPS directly from Visual Studio Code, with full syntax highlighting, file tree navigation, and integrated terminal.
  • Prerequisites
    • Install Visual Studio Code on your computer.
    • Have your server credentials (IP and root password)
  • Step 1: Install Remote - SSH extension
    1. Open VS Code.
    2. Click on the Extensions icon in the left sidebar (or press Ctrl+Shift+X).
    3. Search for Remote - SSH (developed by Microsoft)
    4. Click Install.
  • Step 2: Configure the connection
    1. Click the small green >< icon (or blue) at the bottom-left corner of the VS Code window (or press F1 and type Remote-SSH: Connect to Host...).
    2. Select Connect to Host...
    3. Select Add New SSH Host...
    4. Enter your SSH connection command (the same as in your terminal):
      ssh -p 54321 root@YOUR_VPS_IP
    5. Press Enter.
    6. Choose the first suggested configuration file (usually C:\\Users\\YourName\\.ssh\\config or ~/.ssh/config).
  • Step 3: Connect to the server
    1. A notification appears at the bottom right: Host added
      . Click Connect.
    2. (If the notification disappeared: Click the green icon at the bottom left > Connect to Host... > Select the IP you just added).
    3. A new VS Code window will open.
    4. Select the platform: Linux.
    5. Enter your server’s root password when prompted at the top of the screen.
      Note: Once connected, the green icon at the bottom left will display SSH: YOUR_IP.
  • Step 4: Open the CMS folder
    To work on your files:
    1. In the VS Code window connected to the server, click the Open Folder button in the left explorer.
    2. The search bar at the top will ask for a path. Enter your installation path:/var/www/pragma-cms
    3. Click OK.
    4. VS Code may ask for your password again.
    5. You can now see the full server file structure and edit files directly.

5. Domain Name (DNS)

Now is the time to link your domain name (e.g. my-awesome-site.com) to your VPS, so that the website can be accessed via a web browser.

keep_pin
Important concept
  • A domain name (e.g. my-super-site.com) points to an IP address (your VPS)
  • A subdomain (e.g. site1.my-super-site.com) is just another DNS entry pointing to the same IP
  • DNS does NOT create anything on the server, it only maps names to an IP address

Accessing DNS settings:

  1. Log in to your registrar (recommended: Cloudflare, or OVH, Namecheap, etc.)
  2. Select your domain (my-super-site.com)
  3. Go to the DNS management / DNS records section

Creating the main domain records:

  1. Create or edit an A record:
TypeName (Host)Value (Target)TTLNote
A@YOUR_VPS_IPAutomain domain
CNAMEwwwmy-super-site.comAutowww version

Creating a subdomain (optional):

In most cases, a single subdomain is sufficient to start with (no need for a wildcard – see below).

  1. (Optional) If your management platform is hosted on a specific subdomain:
    Create a second record A:
    • Host/Name : site1
    • Value/Target : YOUR_VPS_IP
    • TTL : Default
      👉 After propagation, you will be able to access: http://name1.my-super-site.com
  1. (Optional – Advanced) Automatically create all subdomains (Wildcard):
    ℹ️ This step is not necessary to get started. Only use it if your CMS needs to handle dynamic subdomains (for demo sites, for example).

    If your CMS needs to handle dynamic subdomains (e.g. name1, name2, name3, etc.), you can use a DNS wildcard.

    Add an A record:
    • Host/Name : *
    • Value/Target : YOUR_VPS_IP
    • TTL : Default

🔍 What this means:

  • name1.my-great-cms.com
  • name2.my-great-cms.com
  • test.my-great-cms.com

👉 They will all automatically point to the VPS, without having to create a DNS record each time.

⚠️ The wildcard does not override explicitly defined subdomains (www, mail, etc.).

warning
Cloudflare specific setup
If you use Cloudflare (recommended for performance and security), adjust SSL settings for Caddy compatibility:
  1. Proxy (Orange Cloud):
    • Make sure the cloud is Orange (Proxied) for both your records (@
      and *). This protects your IP address and enables the CDN.
  2. SSL Mode (Crucial):
    • Go to the SSL/TLS > Overview menu.
    • Select Full (Strict) mode.
    • Why? Your Caddy server generates its own certificates. If you remain in ‘Flexible’ mode, Cloudflare will attempt to communicate via HTTP with your server, which expects HTTPS, creating an infinite redirect loop.
  1. Verification
    (It can take anywhere from 10 minutes to 24 hours, but it’s often quick).

6. Workflow and Customization

Once the platform is installed, it is important to understand where and how to work safely without breaking future updates.

Golden rule: Never modify files in cms-versions/.

This folder contains the software’s source code (the engine). If you modify it, your changes will be overwritten the next time the system is updated.

Here are the two recommended methods for working on your websites:

  • Method A: Via the Control Panel (Recommended)
    For 95% of tasks, you don’t need to touch the server files. Pragma CMS includes powerful tools:
    1. Content creation: Use the Page Builder to create complex layouts.
    2. Design & CSS: Go to ThemesEditor
      • The built-in code editor (Monaco) allows you to safely edit the CSS, JS and Twig templates of your active themes.
      • The CMS automatically manages permissions and caching.
  1. Configuration: Everything is managed via the Site Settings.
  • Method B: Via VS Code / SFTP (For developers)
    If you need to develop a complex theme, add large files (fonts, videos) or debug, you can work directly on the files.
    Thanks to the ACL configuration (set up in previous steps), you can create and edit files using your SSH user without blocking the web server.
    Where to work?
    Everything takes place in the folder: /var/www/pragma-cms/sites/
     Each site you create has its own isolated folder:
BASH
/sites/
  └── my-site/               <-- Site directory (identified by its “handle”)
       ├── assets/           <-- Global static resources (fonts, shared libraries, icons)
       ├── content-types/    <-- PHP definitions of the data structure (Blueprints: Page, Blog...)
       ├── database/         <-- Database migrations specific to this site
       ├── extensions/       <-- Extensions/plugins installed for this site only
       ├── lang/             <-- Site-specific translation files (i18n)
       ├── media/            <-- Media library: contains source images and generated variants
       ├── pages/            <-- Specific PHP controllers (custom page logic)
       ├── storage/          <-- Temporary files, Twig cache, system logs
       ├── templates/        <-- Global Twig templates (emails, basic non-theme layouts)
       ├── themes/           <-- This is where you work on the design
       │    └── my-theme/   
       │         ├── assets/ (CSS, JS, theme-specific images)
       │         └── templates/ (Theme .twig files)
       └── uploads/          <-- Storage for miscellaneous files (PDF, Zip) or temporary files set up in previous steps

Example developer workflow:

  1. Connect using VS Code (Remote SSH).
  2. Open the folder /var/www/pragma-cms/sites/client-xyz/themes/my-theme/.
  3. Edit your style.css or home.twig templates.
  4. Save. The changes will take effect immediately online.
Note:  If you create a new folder or file via VS Code, the ACL permissions you set up earlier will automatically ensure that the web server can read them. You won’t need to run any chown or chmod commands again.

7. Automated Maintenance (Cron & Backup)

check_circle
If you used the installation script, everything is already configured!
  • Backups: daily at 03:00 in /var/backups/pragma-cms
  • Updates check: every 12 hours
  • Staging deploy script available:sudo /var/www/pragma-cms/scripts/cli/deploy_staging.sh
Manual scheduled tasks setup
Once you have installed the server and the CMS, you need to set up routines for backing up your data, deploying to the staging environment, and monitoring your server.
  • 7.1 Utility scripts
    • Backup script backup.sh
      Create the file in the CMS directory: /var/www/pragma-cms/scripts/cron/backup.sh:
BASH
#!/bin/bash
set -euo pipefail

# CONFIG
BACKUP_DIR="/var/backups/pragma-cms"
DATE=$(date +"%Y-%m-%d_%H-%M")
DB_USER="pragma_master"
DB_PASS="YOUR_PASSWORD_HERE"  # Replace with the actual password
KEEP_DAYS=7

# Create the backup directory
mkdir -p $BACKUP_DIR

# 1. INTELLIGENT DATABASE BACKUP
databases=$(mysql -u $DB_USER -p$DB_PASS -e "SHOW DATABASES;" -s --skip-column-names | grep -Ev "^(information_schema|performance_schema|mysql|sys)$")

for db in $databases; do
    echo " - Dumping DB: $db..."
    mysqldump -u $DB_USER -p$DB_PASS $db | gzip &gt; "$BACKUP_DIR/db_${db}_$DATE.sql.gz"
done

# 2. Backup Files
tar -czf "$BACKUP_DIR/files_$DATE.tar.gz" \
    --exclude='storage/cache/*' \
    --exclude='storage/logs/*' \
    --exclude='storage/tmp/*' \
    /var/www/pragma-cms

# 3. Cleanup old backups
find $BACKUP_DIR -type f -name "*.gz" -mtime +$KEEP_DAYS -delete
  • ⚠️ Security: Ensure that only root can read this script and the folder backups:
BASH
# Make the script executable and secure (root-only read, since it contains the password)
chmod 700 /var/www/pragma-cms/scripts/cron/backup.sh
chown root:root /var/www/pragma-cms/scripts/cron/backup.sh
# Remove ACLs specifically for this sensitive file to prevent the sys_user from reading it
setfacl -b /var/www/pragma-cms/scripts/cron/backup.sh
  • Staging deployment script deploy_staging.sh
    Create /var/www/pragma-cms/scripts/cli/deploy_staging.sh:
BASH
#!/bin/bash
set -euo pipefail

# ===============================================================
# PRAGMA CMS - SYNC PROD -&gt; STAGING
# ⚠️ WARNING: THIS WILL OVERWRITE THE ENTIRE STAGING
# ===============================================================

read -p "⚠️  This will overwrite the STAGING database and files with those from PROD. Continue? (y/n) " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    exit 1
fi

DB_USER="pragma_master"
read -sp "DB password ($DB_USER): " DB_PASS
echo ""

echo "🔄 1/3 Cloning the database..."
mysqldump -u $DB_USER -p$DB_PASS pragma_cms_platform | mysql -u $DB_USER -p$DB_PASS pragma_cms_platform_staging

echo "📂 2/3 Syncing files..."
rsync -av --delete \
    --exclude 'config_db.php' \
    --exclude 'storage/cache/*' \
    --exclude 'storage/logs/*' \
    /var/www/pragma-cms/ \
    /var/www/pragma-cms-staging/

echo "🔧 3/3 Adjusting permissions..."
chown -R www-data:www-data /var/www/pragma-cms-staging

echo "✅ Synchronization completed!"
echo "The staging environment is now an exact clone of production."
  • This script overwrites the staging environment with the latest production version and saves a backup before each operation.
  • ⚠️ Security: Set permissions to 700 for the staging environment as well.
  • 7.2 Cron jobs
    To automate backups and the workflow, add the following lines to the root crontab (sudo crontab -e) :
BASH
# -------------------------------
# Daily PROD backup
# -------------------------------
0 3 * * * /var/www/pragma-cms/scripts/cron/backup.sh &gt;/var/www/pragma-cms/storage/logs/cron_backup.log 2&gt;&amp;1

# -------------------------------
# Check for CMS updates
# -------------------------------
0 4,16 * * * sudo -u www-data /usr/bin/php /var/www/pragma-cms/scripts/cron/check_updates.php &gt;&gt; /var/www/pragma-cms/storage/logs/cron_update.log 2&gt;&amp;1
  • The logs will be saved in /var/log/pragma_backup.log
    and /var/log/pragma_update.log.
  • ⚠️ Check that root has access to /var/log
    and that there is sufficient space.
  • 7.3 Post-installation checks
    Before considering the server ready for use:
    1. Active services:
BASH
systemctl status php8.4-fpm
systemctl status caddy
systemctl status mariadb
systemctl status fail2ban
  1. PHP Test:
BASH
curl -s http://localhost/test.php | grep"PHP Version"
  1. Caddy/HTTPS Test :
    • Check your domains (production and staging) via a web browser.
    • Logs : /var/log/caddy/platform-access.log
       and /var/log/caddy/staging-access.log
  2. Backup test:
BASH
sudo /var/www/pragma-cms/scripts/cron/backup.sh
ls -lh /var/backups/pragma-cms
  1. Staging Test:
BASH
sudo /var/www/pragma-cms/scripts/cli/deploy_staging.sh
  • Please check that the files and databases are properly synchronised.
  • 7.4 Safety and maintenance notes
    • Change the pragma_master password regularly if several people have access.
    • Check the Fail2Ban logs: sudo fail2ban-client status sshd
    • Clear /var/log and /root/backups if disk space is running low.
    • Check OPcache: your 99-pragma.ini must be active (FPM must be restarted after each change).