<!DOCTYPE html>
< html lang = "en" dir = "ltr" >
< head >
< meta charset = "utf-8" / >
< title > documentation:2.0:configvhost< / title >
< meta name = "generator" content = "DokuWiki" / >
< meta name = "robots" content = "index,follow" / >
< meta name = "keywords" content = "documentation,2.0,configvhost" / >
< link rel = "search" type = "application/opensearchdescription+xml" href = "lib/exe/opensearch.html" title = "LemonLDAP::NG" / >
< link rel = "start" href = "configvhost.html" / >
< link rel = "contents" href = "configvhost.html" title = "Sitemap" / >
< link rel = "stylesheet" type = "text/css" href = "lib/exe/css.php.t.bootstrap3.css" / >
<!-- //if:usedebianlibs
< link rel = "stylesheet" type = "text/css" href = "/javascript/bootstrap/css/bootstrap.min.css" / >
//elsif:useexternallibs
< link rel = "stylesheet" type = "text/css" href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" > < / script >
//elsif:cssminified
< link rel = "stylesheet" type = "text/css" href = "/static/bwr/bootstrap/dist/css/bootstrap.min.css" / >
//else -->
< link rel = "stylesheet" type = "text/css" href = "/static/bwr/bootstrap/dist/css/bootstrap.css" / >
<!-- //endif -->
< script type = "text/javascript" > / * < ! [ C D A T A [ * / v a r N S = ' d o c u m e n t a t i o n : 2 . 0 ' ; v a r J S I N F O = { " i d " : " d o c u m e n t a t i o n : 2 . 0 : c o n f i g v h o s t " , " n a m e s p a c e " : " d o c u m e n t a t i o n : 2 . 0 " } ;
/*!]]>*/< / script >
< script type = "text/javascript" charset = "utf-8" src = "lib/exe/js.php.t.bootstrap3.js" > < / script >
<!-- //if:usedebianlibs
< script type = "text/javascript" src = "/javascript/jquery/jquery.min.js" > < / script >
//elsif:useexternallibs
< script type = "text/javascript" src = "http://code.jquery.com/jquery-2.2.0.min.js" > < / script >
//elsif:jsminified
< script type = "text/javascript" src = "/static/bwr/jquery/dist/jquery.min.js" > < / script >
//else -->
< script type = "text/javascript" src = "/static/bwr/jquery/dist/jquery.js" > < / script >
<!-- //endif -->
<!-- //if:usedebianlibs
< script type = "text/javascript" src = "/javascript/jquery-ui/jquery-ui.min.js" > < / script >
//elsif:useexternallibs
< script type = "text/javascript" src = "http://code.jquery.com/ui/1.10.4/jquery-ui.min.js" > < / script >
//elsif:jsminified
< script type = "text/javascript" src = "/static/bwr/jquery-ui/jquery-ui.min.js" > < / script >
//else -->
< script type = "text/javascript" src = "/static/bwr/jquery-ui/jquery-ui.js" > < / script >
<!-- //endif -->
< / head >
< body >
< div class = "dokuwiki export container" >
<!-- TOC START -->
< div id = "dw__toc" >
< h3 class = "toggle" > Table of Contents< / h3 >
< div >
< ul class = "toc" >
< li class = "level1" > < div class = "li" > < a href = "#apache_configuration" > Apache configuration< / a > < / div >
< ul class = "toc" >
< li class = "level2" > < div class = "li" > < a href = "#hosted_application" > Hosted application< / a > < / div > < / li >
< li class = "level2" > < div class = "li" > < a href = "#reverse_proxy" > Reverse proxy< / a > < / div > < / li >
< li class = "level2" > < div class = "li" > < a href = "#add_a_floating_menu" > Add a floating menu< / a > < / div > < / li >
< / ul >
< / li >
< li class = "level1" > < div class = "li" > < a href = "#nginx_configuration" > Nginx configuration< / a > < / div >
< ul class = "toc" >
< li class = "level2" > < div class = "li" > < a href = "#hosted_application1" > Hosted application< / a > < / div > < / li >
< li class = "level2" > < div class = "li" > < a href = "#reverse_proxy1" > Reverse proxy< / a > < / div > < / li >
< / ul >
< / li >
< li class = "level1" > < div class = "li" > < a href = "#lemonldapng_configuration" > LemonLDAP::NG configuration< / a > < / div >
< ul class = "toc" >
< li class = "level2" > < div class = "li" > < a href = "#access_rules_and_http_headers" > Access rules and HTTP headers< / a > < / div > < / li >
< li class = "level2" > < div class = "li" > < a href = "#post_data" > POST data< / a > < / div > < / li >
< li class = "level2" > < div class = "li" > < a href = "#options" > Options< / a > < / div > < / li >
< / ul > < / li >
< / ul >
< / div >
< / div >
<!-- TOC END -->
< h1 class = "sectionedit1" id = "manage_virtual_hosts" > Manage virtual hosts< / h1 >
< div class = "level1" >
< p >
LemonLDAP::NG configuration is build around Apache or Nginx virtual hosts. Each virtual host is a protected resource, with access rules, headers, POST data and options.
< / p >
< / div >
<!-- EDIT1 SECTION "Manage virtual hosts" [1 - 206] -->
< h2 class = "sectionedit2" id = "apache_configuration" > Apache configuration< / h2 >
< div class = "level2" >
< p >
To protect a virtual host in Apache, the LemonLDAP::NG Handler must be activated (see < a href = "configlocation.html#apache" class = "wikilink1" title = "documentation:2.0:configlocation" > Apache global configuration< / a > ).
< / p >
< p >
Then you can take any virtual host, and simply add this line to protect it:
< / p >
< pre class = "code file apache" > PerlHeaderParserHandler Lemonldap::NG::Handler< / pre >
< / div >
<!-- EDIT2 SECTION "Apache configuration" [207 - 530] -->
< h3 class = "sectionedit3" id = "hosted_application" > Hosted application< / h3 >
< div class = "level3" >
< p >
Example of a protected virtual host for a local application:
< / p >
< pre class = "code file apache" > < < span class = "kw3" > VirtualHost< / span > *:< span class = "nu0" > 80< / span > >
< span class = "kw1" > ServerName< / span > localsite.example.com
PerlHeaderParserHandler Lemonldap::NG::Handler
< span class = "kw1" > DocumentRoot< / span > /var/www/localsite
< span class = "kw1" > ErrorLog< / span > /var/log/apache2/localsite_error.log
< span class = "kw1" > CustomLog< / span > /var/log/apache2/localsite_access.log combined
< /< span class = "kw3" > VirtualHost< / span > > < / pre >
< / div >
<!-- EDIT3 SECTION "Hosted application" [531 - 938] -->
< h3 class = "sectionedit4" id = "reverse_proxy" > Reverse proxy< / h3 >
< div class = "level3" >
< p >
Example of a protected virtual host with LemonLDAP::NG as reverse proxy:
< / p >
< pre class = "code file apache" > < < span class = "kw3" > VirtualHost< / span > *:< span class = "nu0" > 80< / span > >
< span class = "kw1" > ServerName< / span > application.example.com
PerlHeaderParserHandler Lemonldap::NG::Handler
< span class = "co1" > # Reverse-Proxy< / span >
< span class = "kw1" > ProxyPass< / span > / http://private-name/
< span class = "co1" > # Change " Location" header in redirections< / span >
< span class = "kw1" > ProxyPassReverse< / span > / http://private-name/
< span class = "co1" > # Change domain cookies< / span >
< span class = "kw1" > ProxyPassReverseCookieDomain< / span > private-name application.example.com
< span class = "kw1" > ErrorLog< / span > /var/log/apache2/proxysite_error.log
< span class = "kw1" > CustomLog< / span > /var/log/apache2/proxysite_access.log combined
< /< span class = "kw3" > VirtualHost< / span > > < / pre >
< p >
Same with remote server configured with the same host name:
< / p >
< pre class = "code file apache" > < < span class = "kw3" > VirtualHost< / span > *:< span class = "nu0" > 80< / span > >
< span class = "kw1" > ServerName< / span > application.example.com
PerlHeaderParserHandler Lemonldap::NG::Handler
< span class = "co1" > # Reverse-Proxy< / span >
< span class = "kw1" > ProxyPass< / span > / http://APPLICATION_IP/
< span class = "kw1" > ProxyPreserveHost< / span > < span class = "kw2" > on< / span >
< span class = "kw1" > ErrorLog< / span > /var/log/apache2/proxysite_error.log
< span class = "kw1" > CustomLog< / span > /var/log/apache2/proxysite_access.log combined
< /< span class = "kw3" > VirtualHost< / span > > < / pre >
< div class = "noteclassic" > The < code > ProxyPreserveHost< / code > directive will forward the Host header to the protected application.< br / >
To learn more about using Apache as reverse-proxy, see < a href = "http://httpd.apache.org/docs/current/mod/mod_proxy.html" class = "urlextern" title = "http://httpd.apache.org/docs/current/mod/mod_proxy.html" rel = "nofollow" > Apache documentation< / a > .
< / div > < div class = "notetip" > Some applications need the < code > REMOTE_USER< / code > environment variable to get the connected user, which is not set in reverse-proxy mode. In this case, see < a href = "header_remote_user_conversion.html" class = "wikilink1" title = "documentation:2.0:header_remote_user_conversion" > how convert header into environment variable< / a > .
< / div >
< / div >
<!-- EDIT4 SECTION "Reverse proxy" [939 - 2531] -->
< h3 class = "sectionedit5" id = "add_a_floating_menu" > Add a floating menu< / h3 >
< div class = "level3" >
< p >
A little floating menu can be added to application with this simple Apache configuration:
< / p >
< pre class = "code file apache" > PerlModule Lemonldap::NG::Handler::Menu
PerlOutputFilterHandler Lemonldap::NG::Handler::Menu-> run< / pre >
< p >
Pages where this menu is displayed can be restricted, for example:
< / p >
< pre class = "code file apache" > < < span class = "kw3" > Location< / span > /var/www/html/index.php>
PerlOutputFilterHandler Lemonldap::NG::Handler::Menu-> run
< /< span class = "kw3" > Location< / span > > < / pre >
< div class = "noteimportant" > You need to disable mod_deflate to use the floating menu
< / div >
< / div >
<!-- EDIT5 SECTION "Add a floating menu" [2532 - 3048] -->
< h2 class = "sectionedit6" id = "nginx_configuration" > Nginx configuration< / h2 >
< div class = "level2" >
< p >
To protect a virtual host in Nginx, the LemonLDAP::NG FastCGI server must be launched (see < a href = "fastcgiserver.html" class = "wikilink1" title = "documentation:2.0:fastcgiserver" > LemonLDAP::NG FastCGI server< / a > ).
< / p >
< p >
Then you can take any virtual host and modify it:
< / p >
< ul >
< li class = "level1" > < div class = "li" > Declare the /lmauth endpoint< / div >
< / li >
< / ul >
< pre class = "code file nginx" > location = /lmauth {
internal;
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/run/llng-fastcgi-server/llng-fastcgi.sock;
# Drop post datas
fastcgi_pass_request_body off;
fastcgi_param CONTENT_LENGTH " " ;
# Keep original hostname
fastcgi_param HOST $http_host;
# Keep original request (LLNG server will received /llauth)
fastcgi_param X_ORIGINAL_URI $request_uri;
}< / pre >
< ul >
< li class = "level1" > < div class = "li" > Protect the application (/ or /path/to/protect):< / div >
< / li >
< / ul >
< pre class = "code file nginx" > location /path/to/protect {
auth_request /lmauth;
auth_request_set $lmremote_user $upstream_http_lm_remote_user;
auth_request_set $lmlocation $upstream_http_location;
auth_request_set $cookie_value $upstream_http_set_cookie;
add_header Set-Cookie $cookie_value;
error_page 401 $lmlocation;
try_files $uri $uri/ =404;
...
}< / pre >
< ul >
< li class = "level1" > < div class = "li" > Use LUA or set manually the headers:< / div >
< / li >
< / ul >
< pre class = "code file nginx" > location /path/to/protect {
...
# IF LUA IS SUPPORTED
#include /etc/lemonldap-ng/nginx-lua-headers.conf;
# ELSE
# Set manually your headers
#auth_request_set $authuser $upstream_http_auth_user;
#proxy_set_header Auth-User $authuser;
# OR
#fastcgi_param HTTP_AUTH_USER $authuser;
# Then (if LUA not supported), change cookie header to hide LLNG cookie
#auth_request_set $lmcookie $upstream_http_cookie;
#proxy_set_header Cookie: $lmcookie;
# OR in the corresponding block
#fastcgi_param HTTP_COOKIE $lmcookie;
# Set REMOTE_USER (for FastCGI apps only)
#fastcgi_param REMOTE_USER $lmremote_user;
}< / pre >
< / div >
<!-- EDIT6 SECTION "Nginx configuration" [3049 - 4936] -->
< h3 class = "sectionedit7" id = "hosted_application1" > Hosted application< / h3 >
< div class = "level3" >
< p >
Example of a protected virtual host for a local application:
< / p >
< pre class = "code file nginx" > # Log format
include /path/to/lemonldap-ng/nginx-lmlog.conf;
server {
listen 80;
server_name myserver;
root /var/www/html;
# Internal authentication request
location = /lmauth {
internal;
include /etc/nginx/fastcgi_params;
fastcgi_pass /path/to/llng-fastcgi-server.sock;
# Drop post datas
fastcgi_pass_request_body off;
fastcgi_param CONTENT_LENGTH " " ;
# Keep original hostname
fastcgi_param HOST $http_host;
# Keep original request (LLNG server will received /llauth)
fastcgi_param X_ORIGINAL_URI $request_uri;
}
# Client requests
location ~ \.php$ {
auth_request /lmauth;
auth_request_set $lmremote_user $upstream_http_lm_remote_user;
auth_request_set $lmlocation $upstream_http_location;
error_page 401 $lmlocation;
try_files $uri $uri/ =404;
include fastcgi_params;
try_files $fastcgi_script_name =404;
fastcgi_pass /path/to/php-fpm/socket;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors on;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_hide_header X-Powered-By;
##################################
# PASSING HEADERS TO APPLICATION #
##################################
# IF LUA IS SUPPORTED
#include /path/to/nginx-lua-headers.conf
# ELSE
# Set manually your headers
#auth_request_set $authuser $upstream_http_auth_user;
#fastcgi_param HTTP_AUTH_USER $authuser;
}
location / {
try_files $uri $uri/ =404;
}
}< / pre >
< / div >
<!-- EDIT7 SECTION "Hosted application" [4937 - 6566] -->
< h3 class = "sectionedit8" id = "reverse_proxy1" > Reverse proxy< / h3 >
< div class = "level3" >
< p >
Example of a protected reverse-proxy:
< / p >
< pre class = "code file nginx" > # Log format
include /path/to/lemonldap-ng/nginx-lmlog.conf;
server {
listen 80;
server_name myserver;
root /var/www/html;
# Internal authentication request
location = /lmauth {
internal;
include /etc/nginx/fastcgi_params;
fastcgi_pass /path/to/llng-fastcgi-server.sock;
# Drop post datas
fastcgi_pass_request_body off;
fastcgi_param CONTENT_LENGTH " " ;
# Keep original hostname
fastcgi_param HOST $http_host;
# Keep original request (LLNG server will received /llauth)
fastcgi_param X_ORIGINAL_URI $request_uri;
}
# Client requests
location / {
auth_request /lmauth;
auth_request_set $lmremote_user $upstream_http_lm_remote_user;
auth_request_set $lmlocation $upstream_http_location;
error_page 401 $lmlocation;
proxy_pass http://remote.server/;
include /etc/nginx/proxy_params;
##################################
# PASSING HEADERS TO APPLICATION #
##################################
# IF LUA IS SUPPORTED
#include /path/to/nginx-lua-headers.conf
# ELSE
# Set manually your headers
#auth_request_set $authuser $upstream_http_auth_user;
#proxy_set_header HTTP_AUTH_USER $authuser;
}
}< / pre >
< / div >
<!-- EDIT8 SECTION "Reverse proxy" [6567 - 7861] -->
< h2 class = "sectionedit9" id = "lemonldapng_configuration" > LemonLDAP::NG configuration< / h2 >
< div class = "level2" >
< p >
A virtual host protected by LemonLDAP::NG Handler must be registered in LemonLDAP::NG configuration.
< / p >
< p >
To do this, use the Manager, and go in < code > Virtual Hosts< / code > branch. You can add, delete or modify a virtual host here. Enter the exact virtual host name (for example < code > test.example.com< / code > ) or use a wildcard (for example < code > *.example.com< / code > ).
< / p >
< p >
A virtual host contains:
< / p >
< ul >
< li class = "level1" > < div class = "li" > Access rules: check user' s right on < abbr title = "Uniform Resource Locator" > URL< / abbr > patterns< / div >
< / li >
< li class = "level1" > < div class = "li" > HTTP headers: forge information sent to protected applications< / div >
< / li >
< li class = "level1" > < div class = "li" > POST data: use form replay< / div >
< / li >
< li class = "level1" > < div class = "li" > Options: redirection port and protocol< / div >
< / li >
< / ul >
< / div >
<!-- EDIT9 SECTION "LemonLDAP::NG configuration" [7862 - 8461] -->
< h3 class = "sectionedit10" id = "access_rules_and_http_headers" > Access rules and HTTP headers< / h3 >
< div class = "level3" >
< p >
See < strong > < a href = "writingrulesand_headers.html" class = "wikilink1" title = "documentation:2.0:writingrulesand_headers" > Writing rules and headers< / a > < / strong > to learn how to configure access control and HTTP headers sent to application by < abbr title = "LemonLDAP::NG" > LL::NG< / abbr > .
< / p >
< / div >
<!-- EDIT10 SECTION "Access rules and HTTP headers" [8462 - 8654] -->
< h3 class = "sectionedit11" id = "post_data" > POST data< / h3 >
< div class = "level3" >
< p >
See < strong > < a href = "formreplay.html" class = "wikilink1" title = "documentation:2.0:formreplay" > Form replay< / a > < / strong > to learn how to configure form replay to POST data on protected applications.
< / p >
< / div >
<!-- EDIT11 SECTION "POST data" [8655 - 8789] -->
< h3 class = "sectionedit12" id = "options" > Options< / h3 >
< div class = "level3" >
< p >
Some options are available:
< / p >
< ul >
< li class = "level1" > < div class = "li" > Port: used to build redirection < abbr title = "Uniform Resource Locator" > URL< / abbr > < em > (when user is not logged, or for < abbr title = "Cross Domain Authentication" > CDA< / abbr > requests)< / em > < / div >
< / li >
< li class = "level1" > < div class = "li" > HTTPS: used to build redirection < abbr title = "Uniform Resource Locator" > URL< / abbr > < / div >
< / li >
< li class = "level1" > < div class = "li" > Maintenance mode: reject all requests with a maintenance message< / div >
< / li >
< li class = "level1" > < div class = "li" > Aliases: list of aliases for this virtual host < em > (avoid to rewrite rules,…)< / em > < / div >
< / li >
< li class = "level1" > < div class = "li" > Type: handler type < em > (normal, < a href = "devopshandler.html" class = "wikilink1" title = "documentation:2.0:devopshandler" > DevOps Handler< / a > ,…)< / em > < / div >
< / li >
< li class = "level1" > < div class = "li" > Authentication level required: this options avoid to reject user with a rule based on < code > $_authenticationLevel< / code > . When user hasn' t the required level, he is redirected to an upgrade page in the portal< / div >
< / li >
< / ul >
< p >
“Port” and “HTTPS” options are used to build redirection < abbr title = "Uniform Resource Locator" > URL< / abbr > < em > (when user is not logged, or for < abbr title = "Cross Domain Authentication" > CDA< / abbr > requests)< / em > . By default, default values are used. These options are only here to override default values.
< / p >
< / div >
<!-- EDIT12 SECTION "Options" [8790 - ] --> < / div >
< / body >
< / html >