Vés al contingut

Desplega amb Apache ​

Allotja BentoPDF amb Apache HTTP Server.

Requisits previs ​

  • Apache 2.4+
  • mod_rewrite activat
  • Certificat SSL (recomanat)

Pas 1: compila el projecte ​

bash
git clone https://github.com/alam00000/bentopdf.git
cd bentopdf
npm install
npm run build

Per personalitzar la marca, defineix variables d'entorn abans de compilar:

bash
VITE_BRAND_NAME="AcmePDF" VITE_BRAND_LOGO="images/acme-logo.svg" npm run build

Pas 2: copia els fitxers ​

bash
sudo mkdir -p /var/www/bentopdf
sudo cp -r dist/* /var/www/bentopdf/
sudo chown -R www-data:www-data /var/www/bentopdf

Pas 3: configuració d'Apache ​

Crea /etc/apache2/sites-available/bentopdf.conf:

apache
<VirtualHost *:80>
    ServerName your-domain.com
    Redirect permanent / https://your-domain.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName your-domain.com
    DocumentRoot /var/www/bentopdf

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/your-domain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/your-domain.com/privkey.pem

    <Directory /var/www/bentopdf>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    # WASM MIME type
    AddType application/wasm .wasm

    # Prevent double-compression of pre-compressed files
    SetEnvIfNoCase Request_URI "\.gz$" no-gzip

    # Compression
    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/html text/plain text/css application/javascript application/json application/wasm
    </IfModule>

    # Cache headers
    <IfModule mod_expires.c>
        ExpiresActive On
        ExpiresByType application/javascript "access plus 1 year"
        ExpiresByType text/css "access plus 1 year"
        ExpiresByType application/wasm "access plus 1 year"
        ExpiresByType image/png "access plus 1 year"
        ExpiresByType image/svg+xml "access plus 1 year"
    </IfModule>

    # Required headers for SharedArrayBuffer (LibreOffice WASM)
    Header always set Cross-Origin-Embedder-Policy "require-corp"
    Header always set Cross-Origin-Opener-Policy "same-origin"
    Header always set Cross-Origin-Resource-Policy "cross-origin"

    # Security headers
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"

    # Pre-compressed LibreOffice WASM files
    <FilesMatch "soffice\.wasm\.gz$">
        ForceType application/wasm
        Header set Content-Encoding "gzip"
    </FilesMatch>
    <FilesMatch "soffice\.data\.gz$">
        ForceType application/octet-stream
        Header set Content-Encoding "gzip"
    </FilesMatch>
</VirtualHost>

Pas 4: .htaccess per a l'encaminament ​

Crea /var/www/bentopdf/.htaccess:

apache
RewriteEngine On
RewriteBase /

# Existing files/dirs - serve directly
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

# ============================================
# LANGUAGE ROUTES
# ============================================
# Supported languages: de, es, zh, zh-TW, vi, it, id, tr, fr, pt
# English has no prefix - served from root

# English prefix redirects to root
RewriteRule ^en/?$ / [R=301,L]
RewriteRule ^en/(.+)$ /$1 [R=301,L]

# Language prefix root (e.g., /de/ -> /de/index.html)
RewriteCond %{DOCUMENT_ROOT}/$1/index.html -f
RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/?$ /$1/index.html [L]

# Language prefix with path (e.g., /de/merge-pdf -> /de/merge-pdf.html)
RewriteCond %{DOCUMENT_ROOT}/$1/$2.html -f
RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/([^/]+)/?$ /$1/$2.html [L]

# ============================================
# ADD .HTML EXTENSION (ROOT LEVEL)
# ============================================
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^([^/]+)$ $1.html [L]

ErrorDocument 404 /404.html

Pas 5: activa els mòduls necessaris ​

bash
sudo a2enmod rewrite
sudo a2enmod ssl
sudo a2enmod headers
sudo a2enmod expires
sudo a2enmod deflate

Pas 6: activa el lloc ​

bash
sudo a2ensite bentopdf.conf
sudo apache2ctl configtest
sudo systemctl reload apache2

Desplegament en un subdirectori ​

Per allotjar-lo a /pdf/:

  1. Compila amb la URL base:
bash
BASE_URL=/pdf/ npm run build
  1. Actualitza .htaccess:
apache
RewriteEngine On
RewriteBase /pdf/

# Existing files/dirs - serve directly
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

# Language routes
RewriteRule ^en/?$ /pdf/ [R=301,L]
RewriteRule ^en/(.+)$ /pdf/$1 [R=301,L]

RewriteCond %{DOCUMENT_ROOT}/pdf/$1/index.html -f
RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/?$ /pdf/$1/index.html [L]

RewriteCond %{DOCUMENT_ROOT}/pdf/$1/$2.html -f
RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/([^/]+)/?$ /pdf/$1/$2.html [L]

# Root level .html extension
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^([^/]+)$ $1.html [L]

ErrorDocument 404 /pdf/404.html

Resolució de problemes ​

Errors 404 amb WASM ​

Assegura't que el tipus MIME està configurat:

apache
AddType application/wasm .wasm

Signa PDF o el emplenador de formularis mostra un visor en blanc (error de MIME amb .mjs) ​

Si la consola del navegador mostra:

Failed to load module script: The server responded with a non-JavaScript
MIME type of "application/octet-stream". Strict MIME type checking is
enforced for module scripts per HTML spec.

…i la petició que falla acaba en .mjs, a la configuració d'Apache li falta l'assignació .mjs → application/javascript. El visor de PDF inclòs porta fitxers de mòdul ES amb extensió .mjs, i el mime.types estàndard d'Apache no els inclou per defecte.

Afegeix-ho al VirtualHost o a .htaccess:

apache
AddType application/javascript .mjs

Després recarrega Apache:

bash
sudo apache2ctl configtest && sudo systemctl reload apache2

Per comprovar-ho: a les DevTools del navegador → pestanya Network, troba la petició .mjs que falla i mira la capçalera de resposta Content-Type. Ara hauria de ser application/javascript, no application/octet-stream.

La reescriptura no funciona ​

Comprova que mod_rewrite està activat:

bash
sudo a2enmod rewrite

La conversió de Word/ODT/Excel a PDF no funciona ​

LibreOffice WASM requereix SharedArrayBuffer, que necessita aquestes capçaleres:

apache
Header always set Cross-Origin-Embedder-Policy "require-corp"
Header always set Cross-Origin-Opener-Policy "same-origin"

També necessita un context segur. http://localhost funciona per a proves locals, però http://192.168.x.x o altres IP de la xarxa local normalment requereixen HTTPS. Si les capçaleres hi són però window.crossOriginIsolated continua sent false, comprova si la pàgina s'obre per HTTP sense xifrar des d'un origen que no és de bucle local.

Els fitxers precomprimits .wasm.gz i .data.gz també necessiten un Content-Encoding correcte:

apache
<FilesMatch "soffice\.wasm\.gz$">
    ForceType application/wasm
    Header set Content-Encoding "gzip"
</FilesMatch>
<FilesMatch "soffice\.data\.gz$">
    ForceType application/octet-stream
    Header set Content-Encoding "gzip"
</FilesMatch>

Assegura't que mod_headers està activat: sudo a2enmod headers

Permís denegat ​

bash
sudo chown -R www-data:www-data /var/www/bentopdf
sudo chmod -R 755 /var/www/bentopdf

Doble llicència: AGPL-3.0 i llicència comercial.