Questa guida spiega come installare e far funzionare LibreBooking (fork di MRBS) in una sottodirectory di un sito, con WordPress installato nella root. L’obiettivo tipico è raggiungere l’app a un URL come https://esempio.it/prenotazioni/ servendo i file pubblici dalla cartella Web/ dell’applicazione.
Punti chiave da ricordare:
- La parte pubblica di LibreBooking è in Web/.
- Nel file config/config.phpimposta$conf['script']['url']coerente con l’URL pubblico.
- Le cartelle tpl/etpl_c/devono essere scrivibili dal web server (Smarty compila i template intpl_c/).
Prerequisiti
- Server web (Apache o nginx) con PHP (consigliato PHP-FPM) e MySQL/MariaDB.
- Estensioni PHP comuni: mysqliopdo_mysql,mbstring,intl,json,xml.
- mod_rewrite attivo su Apache e AllowOverride All dove serve.
Struttura delle cartelle
/var/www/html/
├── index.php                 ← WordPress (root del sito)
├── wp-content/ …
└── prenotazioni/             ← LibreBooking
    ├── Web/                  ← entrypoint pubblico
    │   └── index.php
    ├── config/
    │   ├── config.dist.php
    │   └── config.php
    ├── tpl/                  ← template sorgente
    └── tpl_c/                ← cache Smarty (scrivibile)
Database
CREATE DATABASE librebooking CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'lb_user'@'localhost' IDENTIFIED BY 'password_sicura';
GRANT ALL PRIVILEGES ON librebooking.* TO 'lb_user'@'localhost';
FLUSH PRIVILEGES;
Configurazione di LibreBooking
Copia config/config.dist.php in config/config.php e imposta almeno:
<?php
$conf['script']['url'] = 'https://esempio.it/prenotazioni/Web';
$conf['db']['type']     = 'mysqli';
$conf['db']['host']     = 'localhost';
$conf['db']['name']     = 'librebooking';
$conf['db']['user']     = 'lb_user';
$conf['db']['password'] = 'password_sicura';
date_default_timezone_set('Europe/Rome'); Permessi delle cartelle
Imposta i permessi per l’utente del web server (es. www-data, apache, nginx):
cd /var/www/html/prenotazioni
mkdir -p tpl tpl_c
sudo chown -R www-data:www-data tpl tpl_c
sudo chmod -R 755 tpl tpl_c
# Durante l'installazione, se necessario:
sudo chown -R www-data:www-data config
sudo chmod -R 775 config
WordPress in root: regole di esclusione
Nel .htaccess della root (dove c’è WordPress), aggiungi una regola che bypassi la sottocartella prima del blocco WP:
RewriteEngine On
RewriteRule ^prenotazioni/ - [L]
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
 
# END WordPress
.htaccess nella sottodirectory di LibreBooking
Nel file /var/www/html/prenotazioni/.htaccess usa destinazioni relative (senza / iniziale) per redirigere verso Web/. In una .htaccess di sottodirectory, lo slash iniziale indirizzerebbe la radice del vHost, causando 404/loop.
RewriteEngine On
# Durante i test usa 302; a regime usa 301
RewriteRule ^$ Web/ [R=302,L]
RewriteRule !^Web/ Web/$0 [R=302,L]
Options -Indexes
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
 
# Non inserire direttive php_value qui se usi PHP-FPM
Require all denied
  Alternativa nginx (con PHP-FPM)
Servire esplicitamente /prenotazioni/Web/
server {
    listen 80;
    server_name esempio.it;
    root /var/www/html;
    index index.php index.html;
    location /prenotazioni/Web/ {
        index index.php;
        try_files $uri $uri/ /booking/Web/index.php?$args;
        location ~* \.(ini|dist|md|lock|env|ya?ml)$ { deny all; }
        autoindex off;
    }
    location ~ ^/prenotazioni/Web/.*\.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include snippets/fastcgi-php.conf;
    }
location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include snippets/fastcgi-php.conf;
}
location ~* .(ini|dist|md|lock|env|yml|yaml)$ { deny all; }
autoindex off;
} Alias “pulito” /prenotazioni/ → cartella fisica /prenotazioni/Web/
server {
    listen 80;
    server_name esempio.it;
location /prenotazioni/ {
    alias /var/www/html/prenotazioni/Web/;
    index index.php index.html;
    try_files $uri $uri/ /index.php$args;
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        # Con alias va impostato manualmente:
        fastcgi_param SCRIPT_FILENAME /var/www/html/prenotazioni/Web/$fastcgi_script_name;
        include snippets/fastcgi-php.conf;
    }
}
location ~* .(ini|dist|md|lock|env|yml|yaml)$ { deny all; }
autoindex off;
} Se usi l’alias per nascondere /Web/, imposta $conf['script']['url'] a https://esempio.it/prenotazioni/ per coerenza.
Smoke test
- Crea prenotazioni/Web/ping.txtcon contenutooke visita/prenotazioni/Web/ping.txt: deve dare 200.
- Visita /prenotazioni/: deve redirigere a/prenotazioni/Web/(302 finché testi).
- Crea prenotazioni/Web/phpinfo.phpcon<?php phpinfo();e verifica che PHP risponda.
Troubleshooting: 500 vs 404
- 500 (Internal Server Error): spesso direttive non permesse in .htaccess(php_valuecon FPM), moduli mancanti (Headersenzamod_headers), permessi insufficenti sutpl_c/oconfig/, estensioni PHP non caricate.
- 404: in genere la richiesta finisce su WordPress (manca la regola di bypass in root) o le regole di prenotazioni/.htaccessusano destinazioni con/iniziale.
Controlla i log del server:
# Apache (Debian/Ubuntu)
tail -n 100 /var/log/apache2/error.log
# Apache (RHEL/CentOS)
tail -n 100 /var/log/httpd/error_log
# nginx
tail -n 100 /var/log/nginx/error.log Best practice di sicurezza
- Esporre pubblicamente solo la cartella Web/(o un alias che la mappi), non l’intera app.
- Bloccare l’accesso a file sensibili (.env,.dist,.ini, ecc.).
- Evitare chmod 777; preferire owner o group corretti.
- Non usare php_valuein.htaccesscon PHP-FPM; configurare inphp.inio nel pool FPM.
- Impostare session.autostart = 0edate.timezonecoerente.
Note importanti su rewrite in .htaccess
- In una .htaccessdi sottodirectory le sostituzioni dovrebbero essere relative (niente/iniziale). Esempio corretto:RewriteRule !^Web/ Web/$0.
- La regola di bypass in root per WordPress evita che le richieste a /prenotazioni/cadano nell’index.php del CMS.
Checklist finale
- mod_rewriteattivo e AllowOverride All dove serve.
- Regola di bypass in root: RewriteRule ^prenotazioni/ - [L]sopra il blocco WordPress.
- In prenotazioni/.htaccessdestinazioni senza/iniziale versoWeb/.
- tpl/e- tpl_c/scrivibili dal web server.
- $conf['script']['url']coerente con l’URL pubblico esposto.
- Redirect 302 → 301 solo quando tutto funziona e la cache del browser è pulita.