# =============================================================================
# LimeSurvey – Production Apache Virtual Host Template
# Apache 2.4 + PHP-FPM via FastCGI (mod_proxy_fcgi)
#
# BEFORE GOING LIVE – replace every value marked with <CHANGE_ME:…>
# =============================================================================
# ---------------------------------------------------------------------------
# Global hardening (place these in httpd.conf / security.conf if you prefer)
# ---------------------------------------------------------------------------
ServerTokens Prod # Hide Apache version from response headers
ServerSignature Off # Hide Apache version from error pages
# ---------------------------------------------------------------------------
# 1. HTTP → HTTPS redirect (port 80)
# ---------------------------------------------------------------------------
<VirtualHost *:80>
ServerName <CHANGE_ME: yourdomain.com>
ServerAlias <CHANGE_ME: www.yourdomain.com>
ServerAdmin <CHANGE_ME: webmaster@yourdomain.com>
# Permanent redirect – every HTTP request is sent to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
# redirect from any port
RewriteCond %{HTTP_HOST} ^([^:]+)
RewriteRule ^ https://%1:443%{REQUEST_URI} [R=301,L]
# Keep minimal logs for redirect traffic
ErrorLog /var/log/apache2/limesurvey_error.log
CustomLog /var/log/apache2/limesurvey_access.log combined
</VirtualHost>
# ---------------------------------------------------------------------------
# 2. HTTPS (port 443) – main production vhost
# ---------------------------------------------------------------------------
<VirtualHost *:443>
ServerName <CHANGE_ME: yourdomain.com>
ServerAlias <CHANGE_ME: www.yourdomain.com>
ServerAdmin <CHANGE_ME: webmaster@yourdomain.com>
# the directory to serve
DocumentRoot /var/www/html/CHANGE_ME
DirectoryIndex index.php index.html
# ---- TLS ---------------------------------------------------------------
SSLEngine on
SSLCertificateFile <CHANGE_ME: /etc/ssl/certs/yourdomain.crt>
SSLCertificateKeyFile <CHANGE_ME: /etc/ssl/private/yourdomain.key>
# If using a CA bundle / intermediate chain:
# SSLCertificateChainFile <CHANGE_ME: /etc/ssl/certs/ca-bundle.crt>
# Recommended TLS hardening (requires Apache 2.4.36+ / mod_ssl)
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\
ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off
# ---- Security headers --------------------------------------------------
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
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"
# Adjust the CSP below to match your actual asset sources before enabling:
# Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';"
# ---- LimeSurvey application --------------------------------------------
# serve under a sub-path using Alias (uncomment below):
# 1. Keep DocumentRoot as /var/www/html
# 2. Uncomment Alias, the <Directory /var/www/html> block, and the RewriteRule redirect
# 3. Change RewriteBase to /limesurvey/
# 4. Update config.php:
# 'components' => ['request' => ['baseUrl' => '/limesurvey']],
# 'config' => ['publicurl' => 'https://<CHANGE_ME: yourdomain.com>/limesurvey'],
#
# Alias /limesurvey <CHANGE_ME: /var/www/html/CHANGE_ME>
#
# Allow access to the DocumentRoot (required for the Alias to function;
# without this Apache falls back to the default "Require all denied").
# <Directory /var/www/html>
# Options -Indexes
# AllowOverride None
# Require all granted
# </Directory>
#
# Redirect any path that does NOT start with /limesurvey to /limesurvey/...
# e.g. /admin → /limesurvey/admin, / → /limesurvey/
# RewriteEngine On
# RewriteRule ^(?!/limesurvey(/|$))(.*)$ /limesurvey/$2 [R=301,L]
# ---- LimeSurvey directory rules ----------------------------------------
<Directory /var/www/html/ls-ce-6x>
Options FollowSymLinks
AllowOverride FileInfo Indexes Limit Options=MultiViews,SymLinksIfOwnerMatch AuthConfig
Require all granted
# Allow PHP to receive PATH_INFO (e.g. index.php/admin)
AcceptPathInfo On
RewriteEngine On
# needs to be changed for target alias if used
RewriteBase /
# 1. Editor SPA: non-existent files under /editor/ fall back to editor's index.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^editor/(.*)$ editor/index.html [L]
# 2. LimeSurvey front-controller: $1 becomes PATH_INFO so /admin → index.php/admin
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
</Directory>
# ---- Block direct access to sensitive directories ----------------------
#<DirectoryMatch "/var/www/html/ls-ce-6x/(application|framework|themes/\w+/views)">
# Require all denied
#</DirectoryMatch>
# ---- Block direct access to sensitive files ----------------------------
#<FilesMatch "(^\.ht|\.log$|\.bak$|\.sql$|\.sh$|composer\.(json|lock)$)">
# Require all denied
#</FilesMatch>
# ---- Proxy all .php requests to PHP-FPM via FastCGI -----------------------------------------------
# CHANGE "127.0.0.1:9000" to match your PHP-FPM listen address/socket.
# Using a Unix socket is faster on the same host:
# SetHandler "proxy:unix:/run/php/php8.x-fpm.sock|fcgi://localhost"
# Or TCP if PHP-FPM is on the same machine:
# SetHandler "proxy:fcgi://127.0.0.1:9000"
<FilesMatch "\.php$">
SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>
# ---- Logging -----------------------------------------------------------
# Adjust paths to match your distro's log directory
ErrorLog /var/log/apache2/limesurvey_error.log
CustomLog /var/log/apache2/limesurvey_access.log combined
LogLevel warn
</VirtualHost>