2 <!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
3 <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
6 <meta http-equiv=
"X-UA-Compatible" content=
"IE=edge">
7 <meta name=
"viewport" content=
"width=device-width, initial-scale=1.0">
10 <link rel=
"shortcut icon" href=
"../img/favicon.ico">
11 <title>Server configuration - Shaarli Documentation
</title>
12 <link href='https://fonts.googleapis.com/css?family=Lato:
400,
700|Roboto+Slab:
400,
700|Inconsolata:
400,
700' rel='stylesheet' type='text/css'
>
14 <link rel=
"stylesheet" href=
"../css/theme.css" type=
"text/css" />
15 <link rel=
"stylesheet" href=
"../css/theme_extra.css" type=
"text/css" />
16 <link rel=
"stylesheet" href=
"../css/highlight.css">
17 <link href=
"../github-markdown.css" rel=
"stylesheet">
21 var mkdocs_page_name = "Server configuration";
22 var mkdocs_page_input_path = "Server-configuration.md";
23 var mkdocs_page_url = "/Server-configuration/";
26 <script src=
"../js/jquery-2.1.1.min.js"></script>
27 <script src=
"../js/modernizr-2.8.3.min.js"></script>
28 <script type=
"text/javascript" src=
"../js/highlight.pack.js"></script>
32 <body class=
"wy-body-for-nav" role=
"document">
34 <div class=
"wy-grid-for-nav">
37 <nav data-toggle=
"wy-nav-shift" class=
"wy-nav-side stickynav">
38 <div class=
"wy-side-nav-search">
39 <a href=
".." class=
"icon icon-home"> Shaarli Documentation
</a>
41 <form id =
"rtd-search-form" class=
"wy-form" action=
"../search.html" method=
"get">
42 <input type=
"text" name=
"q" placeholder=
"Search docs" />
47 <div class=
"wy-menu wy-menu-vertical" data-spy=
"affix" role=
"navigation" aria-label=
"main navigation">
51 <li class=
"toctree-l1">
53 <a class=
"" href=
"..">Home
</a>
56 <li class=
"toctree-l1">
58 <span class=
"caption-text">Setup
</span>
62 <a class=
"" href=
"../Download-and-Installation/">Download and Installation
</a>
66 <a class=
"" href=
"../Upgrade-and-migration/">Upgrade and migration
</a>
70 <a class=
"" href=
"../Server-requirements/">Server requirements
</a>
74 <a class=
"current" href=
"./">Server configuration
</a>
77 <li class=
"toctree-l3"><a href=
"#prerequisites">Prerequisites
</a></li>
81 <li><a class=
"toctree-l4" href=
"#shaarli">Shaarli
</a></li>
83 <li><a class=
"toctree-l4" href=
"#https-tls-and-self-signed-certificates">HTTPS, TLS and self-signed certificates
</a></li>
85 <li><a class=
"toctree-l4" href=
"#proxies">Proxies
</a></li>
90 <li class=
"toctree-l3"><a href=
"#apache">Apache
</a></li>
94 <li><a class=
"toctree-l4" href=
"#minimal">Minimal
</a></li>
96 <li><a class=
"toctree-l4" href=
"#debug-log-all-the-things">Debug - Log all the things!
</a></li>
98 <li><a class=
"toctree-l4" href=
"#standard-keep-access-and-error-logs">Standard - Keep access and error logs
</a></li>
100 <li><a class=
"toctree-l4" href=
"#paranoid-redirect-http-80-to-https-443">Paranoid - Redirect HTTP (:
80) to HTTPS (:
443)
</a></li>
102 <li><a class=
"toctree-l4" href=
"#htaccess">.htaccess
</a></li>
107 <li class=
"toctree-l3"><a href=
"#lighthttpd">LightHttpd
</a></li>
110 <li class=
"toctree-l3"><a href=
"#nginx">Nginx
</a></li>
114 <li><a class=
"toctree-l4" href=
"#foreword">Foreword
</a></li>
116 <li><a class=
"toctree-l4" href=
"#common-setup">Common setup
</a></li>
118 <li><a class=
"toctree-l4" href=
"#optional-increase-the-maximum-file-upload-size">(Optional) Increase the maximum file upload size
</a></li>
120 <li><a class=
"toctree-l4" href=
"#minimal_1">Minimal
</a></li>
122 <li><a class=
"toctree-l4" href=
"#modular">Modular
</a></li>
124 <li><a class=
"toctree-l4" href=
"#redirect-http-to-https">Redirect HTTP to HTTPS
</a></li>
133 <a class=
"" href=
"../Server-security/">Server security
</a>
137 <a class=
"" href=
"../Shaarli-configuration/">Shaarli configuration
</a>
141 <a class=
"" href=
"../Plugins/">Plugins
</a>
146 <li class=
"toctree-l1">
148 <span class=
"caption-text">Docker
</span>
152 <a class=
"" href=
"../Docker-101/">Docker
101</a>
156 <a class=
"" href=
"../Shaarli-images/">Shaarli images
</a>
160 <a class=
"" href=
"../Reverse-proxy-configuration/">Reverse proxy configuration
</a>
164 <a class=
"" href=
"../Docker-resources/">Docker resources
</a>
169 <li class=
"toctree-l1">
171 <span class=
"caption-text">Usage
</span>
175 <a class=
"" href=
"../Features/">Features
</a>
179 <a class=
"" href=
"../Bookmarklet/">Bookmarklet
</a>
183 <a class=
"" href=
"../Browsing-and-searching/">Browsing and searching
</a>
187 <a class=
"" href=
"../Firefox-share/">Firefox share
</a>
191 <a class=
"" href=
"../RSS-feeds/">RSS feeds
</a>
195 <a class=
"" href=
"../REST-API/">REST API
</a>
200 <li class=
"toctree-l1">
202 <span class=
"caption-text">How To
</span>
206 <a class=
"" href=
"../Backup,-restore,-import-and-export/">Backup, restore, import and export
</a>
210 <a class=
"" href=
"../Copy-an-existing-installation-over-SSH-and-serve-it-locally/">Copy an existing installation over SSH and serve it locally
</a>
214 <a class=
"" href=
"../Create-and-serve-multiple-Shaarlis-(farm)/">Create and serve multiple Shaarlis (farm)
</a>
218 <a class=
"" href=
"../Download-CSS-styles-from-an-OPML-list/">Download CSS styles from an OPML list
</a>
222 <a class=
"" href=
"../Datastore-hacks/">Datastore hacks
</a>
227 <li class=
"toctree-l1">
229 <a class=
"" href=
"../Troubleshooting/">Troubleshooting
</a>
232 <li class=
"toctree-l1">
234 <span class=
"caption-text">Development
</span>
238 <a class=
"" href=
"../Development-guidelines/">Development guidelines
</a>
242 <a class=
"" href=
"../Continuous-integration-tools/">Continuous integration tools
</a>
246 <a class=
"" href=
"../GnuPG-signature/">GnuPG signature
</a>
250 <a class=
"" href=
"../Coding-guidelines/">Coding guidelines
</a>
254 <a class=
"" href=
"../Directory-structure/">Directory structure
</a>
258 <a class=
"" href=
"../3rd-party-libraries/">3rd party libraries
</a>
262 <a class=
"" href=
"../Plugin-System/">Plugin System
</a>
266 <a class=
"" href=
"../Release-Shaarli/">Release Shaarli
</a>
270 <a class=
"" href=
"../Versioning-and-Branches/">Versioning and Branches
</a>
274 <a class=
"" href=
"../Security/">Security
</a>
278 <a class=
"" href=
"../Static-analysis/">Static analysis
</a>
282 <a class=
"" href=
"../Theming/">Theming
</a>
286 <a class=
"" href=
"../Unit-tests/">Unit tests
</a>
291 <li class=
"toctree-l1">
293 <span class=
"caption-text">About
</span>
297 <a class=
"" href=
"../FAQ/">FAQ
</a>
301 <a class=
"" href=
"../Community-&-Related-software/">Community & Related software
</a>
311 <section data-toggle=
"wy-nav-shift" class=
"wy-nav-content-wrap">
314 <nav class=
"wy-nav-top" role=
"navigation" aria-label=
"top navigation">
315 <i data-toggle=
"wy-nav-top" class=
"fa fa-bars"></i>
316 <a href=
"..">Shaarli Documentation
</a>
320 <div class=
"wy-nav-content">
321 <div class=
"rst-content">
322 <div role=
"navigation" aria-label=
"breadcrumbs navigation">
323 <ul class=
"wy-breadcrumbs">
324 <li><a href=
"..">Docs
</a> »</li>
328 <li>Setup
»</li>
332 <li>Server configuration
</li>
333 <li class=
"wy-breadcrumbs-aside">
335 <a href=
"https://github.com/shaarli/Shaarli/edit/master/docs/Server-configuration.md"
336 class=
"icon icon-github"> Edit on GitHub
</a>
343 <div class=
"section">
345 <p><em>Example virtual host configurations for popular web servers
</em></p>
347 <li><a href=
"#apache">Apache
</a></li>
348 <li><a href=
"#nginx">Nginx
</a></li>
350 <h2 id=
"prerequisites">Prerequisites
</h2>
351 <h3 id=
"shaarli">Shaarli
</h3>
353 <li>Shaarli is installed in a directory readable/writeable by the user
</li>
354 <li>the correct read/write permissions have been granted to the web server
<em>user and/or group
</em></li>
355 <li>for HTTPS / SSL:
</li>
356 <li>a key pair (public, private) and a certificate have been generated
</li>
357 <li>the appropriate server SSL extension is installed and active
</li>
359 <h3 id=
"https-tls-and-self-signed-certificates">HTTPS, TLS and self-signed certificates
</h3>
361 <em> <a href=
"http://www.xenocafe.com/tutorials/linux/centos/openssl/self_signed_certificates/index.php">How to Create Self-Signed SSL Certificates with OpenSSL
</a>
362 </em> <a href=
"https://workaround.org/certificate-authority">How do I create my own Certificate Authority?
</a>
363 * Generate a self-signed certificate (will trigger browser warnings) with apache2:
<code>make-ssl-cert generate-default-snakeoil --force-overwrite
</code> will create
<code>/etc/ssl/certs/ssl-cert-snakeoil.pem
</code> and
<code>/etc/ssl/private/ssl-cert-snakeoil.key
</code></p>
364 <h3 id=
"proxies">Proxies
</h3>
365 <p>If Shaarli is served behind a proxy (i.e. there is a proxy server between clients and the web server hosting Shaarli), please refer to the proxy server documentation for proper configuration. In particular, you have to ensure that the following server variables are properly set:
366 -
<code>X-Forwarded-Proto
</code>;
367 -
<code>X-Forwarded-Host
</code>;
368 -
<code>X-Forwarded-For
</code>.
</p>
369 <p>See also
<a href=
"https://github.com/shaarli/Shaarli/issues?utf8=%E2%9C%93&q=label%3Aproxy+">proxy-related
</a> issues.
</p>
370 <h2 id=
"apache">Apache
</h2>
371 <h3 id=
"minimal">Minimal
</h3>
372 <pre><code class=
"apache"><VirtualHost *:
80>
373 ServerName shaarli.my-domain.org
374 DocumentRoot /absolute/path/to/shaarli/
378 <h3 id=
"debug-log-all-the-things">Debug - Log all the things!
</h3>
379 <p>This configuration will log both Apache and PHP errors, which may prove useful to identify server configuration errors.
</p>
381 <em> <a href=
"http://stackoverflow.com/q/176">Apache/PHP - error log per VirtualHost
</a> (StackOverflow)
382 </em> <a href=
"https://ma.ttias.be/php-php_value-vs-php_admin_value-and-the-use-of-php_flag-explained/">PHP: php_value vs php_admin_value and the use of php_flag explained
</a></p>
383 <pre><code class=
"apache"><VirtualHost *:
80>
384 ServerName shaarli.my-domain.org
385 DocumentRoot /absolute/path/to/shaarli/
388 ErrorLog /var/log/apache2/shaarli-error.log
389 CustomLog /var/log/apache2/shaarli-access.log combined
391 php_flag log_errors on
392 php_flag display_errors on
393 php_value error_reporting
2147483647
394 php_value error_log /var/log/apache2/shaarli-php-error.log
398 <h3 id=
"standard-keep-access-and-error-logs">Standard - Keep access and error logs
</h3>
399 <pre><code class=
"apache"><VirtualHost *:
80>
400 ServerName shaarli.my-domain.org
401 DocumentRoot /absolute/path/to/shaarli/
404 ErrorLog /var/log/apache2/shaarli-error.log
405 CustomLog /var/log/apache2/shaarli-access.log combined
409 <h3 id=
"paranoid-redirect-http-80-to-https-443">Paranoid - Redirect HTTP (:
80) to HTTPS (:
443)
</h3>
410 <p>See
<a href=
"https://wiki.mozilla.org/Security/Server_Side_TLS#Apache">Server-side TLS
</a> (Mozilla).
</p>
411 <pre><code class=
"apache"><VirtualHost *:
443>
412 ServerName shaarli.my-domain.org
413 DocumentRoot /absolute/path/to/shaarli/
416 SSLCertificateFile /absolute/path/to/the/website/certificate.pem
417 SSLCertificateKeyFile /absolute/path/to/the/website/key.key
419 <Directory /absolute/path/to/shaarli/
>
421 Options Indexes FollowSymLinks MultiViews
427 ErrorLog /var/log/apache2/shaarli-error.log
428 CustomLog /var/log/apache2/shaarli-access.log combined
430 <VirtualHost *:
80>
431 ServerName shaarli.my-domain.org
432 Redirect
301 / https://shaarli.my-domain.org
435 ErrorLog /var/log/apache2/shaarli-error.log
436 CustomLog /var/log/apache2/shaarli-access.log combined
440 <h3 id=
"htaccess">.htaccess
</h3>
441 <p>Shaarli use
<code>.htaccess
</code> Apache files to deny access to files that shouldn't be directly accessed (datastore, config, etc.). You need the directive
<code>AllowOverride All
</code> in your virtual host configuration for them to work.
</p>
442 <p><strong>Warning
</strong>: If you use Apache
2.2 or lower, you need
<a href=
"https://httpd.apache.org/docs/current/mod/mod_version.html">mod_version
</a> to be installed and enabled.
</p>
443 <p>Apache module
<code>mod_rewrite
</code> <strong>must
</strong> be enabled to use the REST API. URL rewriting rules for the Slim microframework are stated in the root
<code>.htaccess
</code> file.
</p>
444 <h2 id=
"lighthttpd">LightHttpd
</h2>
445 <h2 id=
"nginx">Nginx
</h2>
446 <h3 id=
"foreword">Foreword
</h3>
447 <p>Nginx does not natively interpret PHP scripts; to this effect, we will run a
<a href=
"https://en.wikipedia.org/wiki/FastCGI">FastCGI
</a> service, to which Nginx's FastCGI module will proxy all requests to PHP resources.
</p>
448 <p>Required packages:
449 -
<a href=
"http://nginx.org">nginx
</a>
450 -
<a href=
"http://php-fpm.org">php-fpm
</a> - PHP FastCGI Process Manager
</p>
451 <p>Official documentation:
452 -
<a href=
"http://nginx.org/en/docs/beginners_guide.html">Beginner's guide
</a>
453 -
<a href=
"http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html">ngx_http_fastcgi_module
</a>
454 -
<a href=
"http://wiki.nginx.org/Pitfalls">Pitfalls
</a></p>
455 <p>Community resources:
456 -
<a href=
"https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx">Server-side TLS (Nginx)
</a> (Mozilla)
457 -
<a href=
"http://kbeezie.com/nginx-configuration-examples/">PHP configuration examples
</a> (Karl Blessing)
</p>
458 <h3 id=
"common-setup">Common setup
</h3>
459 <p>Once Nginx and PHP-FPM are installed, we need to ensure:
460 - Nginx and PHP-FPM are running using the
<em>same user and group
</em>
461 - both these user and group have
462 -
<code>read
</code> permissions for Shaarli resources
463 -
<code>execute
</code> permissions for Shaarli directories
<em>AND
</em> their parent directories
</p>
464 <p>On a production server:
465 -
<code>user:group
</code> will likely be
<code>http:http
</code>,
<code>www:www
</code> or
<code>www-data:www-data
</code>
466 - files will be located under
<code>/var/www
</code>,
<code>/var/http
</code> or
<code>/usr/share/nginx
</code></p>
467 <p>On a development server:
468 - files may be located in a user's home directory
469 - in this case, make sure both Nginx and PHP-FPM are running as the local user/group!
</p>
470 <p>For all following configuration examples, this user/group pair will be used:
471 -
<code>user:group = john:users
</code>,
</p>
472 <p>which corresponds to the following service configuration:
</p>
473 <pre><code class=
"ini">; /etc/php/php-fpm.conf
482 <pre><code class=
"nginx"># /etc/nginx/nginx.conf
490 <h3 id=
"optional-increase-the-maximum-file-upload-size">(Optional) Increase the maximum file upload size
</h3>
491 <p>Some bookmark dumps generated by web browsers can be
<em>huge
</em> due to the presence of Base64-encoded images and favicons, as well as extra verbosity when nesting links in (sub-)folders.
</p>
492 <p>To increase upload size, you will need to modify both nginx and PHP configuration:
</p>
493 <pre><code class=
"nginx"># /etc/nginx/nginx.conf
498 client_max_body_size
10m;
504 <pre><code class=
"ini"># /etc/php5/fpm/php.ini
509 upload_max_filesize =
10M
512 <h3 id=
"minimal_1">Minimal
</h3>
513 <p><em>WARNING: Use for development only!
</em> </p>
514 <pre><code class=
"nginx">user john users;
517 worker_connections
1024;
522 default_type application/octet-stream;
523 keepalive_timeout
20;
525 index index.html index.php;
529 server_name localhost;
532 access_log /var/log/nginx/access.log;
533 error_log /var/log/nginx/error.log;
536 try_files $uri /shaarli/index.php$is_args$args;
537 access_log /var/log/nginx/shaarli.access.log;
538 error_log /var/log/nginx/shaarli.error.log;
541 location ~ (index)\.php$ {
543 fastcgi_split_path_info ^(.+\.php)(/.+)$;
544 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
545 fastcgi_index index.php;
546 include fastcgi.conf;
552 <h3 id=
"modular">Modular
</h3>
553 <p>The previous setup is sufficient for development purposes, but has several major caveats:
554 - every content that does not match the PHP rule will be sent to client browsers:
555 - dotfiles - in our case,
<code>.htaccess
</code>
556 - temporary files, e.g. Vim or Emacs files:
<code>index.php~
</code>
557 - asset / static resource caching is not optimized
558 - if serving several PHP sites, there will be a lot of duplication:
<code>location /shaarli/
</code>,
<code>location /mysite/
</code>, etc.
</p>
559 <p>To solve this, we will split Nginx configuration in several parts, that will be included when needed:
</p>
560 <pre><code class=
"nginx"># /etc/nginx/deny.conf
562 # deny access to dotfiles
569 # deny access to temp editor files, e.g.
"script.php~
"
576 <pre><code class=
"nginx"># /etc/nginx/php.conf
577 location ~ (index)\.php$ {
578 # Slim - split URL path into (script_filename, path_info)
580 fastcgi_split_path_info ^(.+\.php)(/.+)$;
582 # filter and proxy PHP requests to PHP-FPM
583 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
584 fastcgi_index index.php;
585 include fastcgi.conf;
589 # deny access to all other PHP scripts
594 <pre><code class=
"nginx"># /etc/nginx/static_assets.conf
595 location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
597 add_header Pragma public;
598 add_header Cache-Control
"public, must-revalidate, proxy-revalidate
";
602 <pre><code class=
"nginx"># /etc/nginx/nginx.conf
609 access_log /var/log/nginx/access.log;
610 error_log /var/log/nginx/error.log;
613 # virtual host for a first domain
615 server_name my.first.domain.org;
618 # Slim - rewrite URLs
619 try_files $uri /shaarli/index.php$is_args$args;
621 access_log /var/log/nginx/shaarli.access.log;
622 error_log /var/log/nginx/shaarli.error.log;
625 location = /shaarli/favicon.ico {
626 # serve the Shaarli favicon from its custom location
627 alias /var/www/shaarli/images/favicon.ico;
631 include static_assets.conf;
636 # virtual host for a second domain
638 server_name second.domain.com;
641 access_log /var/log/nginx/minigal.access.log;
642 error_log /var/log/nginx/minigal.error.log;
646 include static_assets.conf;
652 <h3 id=
"redirect-http-to-https">Redirect HTTP to HTTPS
</h3>
653 <p>Assuming you have generated a (self-signed) key and certificate, and they are located under
<code>/home/john/ssl/localhost.{key,crt}
</code>, it is pretty straightforward to set an HTTP (:
80) to HTTPS (:
443) redirection to force SSL/TLS usage.
</p>
654 <pre><code class=
"nginx"># /etc/nginx/nginx.conf
660 index index.html index.php;
663 access_log /var/log/nginx/access.log;
664 error_log /var/log/nginx/error.log;
668 server_name localhost;
670 return
301 https://localhost$request_uri;
675 server_name localhost;
677 ssl_certificate /home/john/ssl/localhost.crt;
678 ssl_certificate_key /home/john/ssl/localhost.key;
681 # Slim - rewrite URLs
682 try_files $uri /index.php$is_args$args;
684 access_log /var/log/nginx/shaarli.access.log;
685 error_log /var/log/nginx/shaarli.error.log;
688 location = /shaarli/favicon.ico {
689 # serve the Shaarli favicon from its custom location
690 alias /var/www/shaarli/images/favicon.ico;
694 include static_assets.conf;
704 <div class=
"rst-footer-buttons" role=
"navigation" aria-label=
"footer navigation">
706 <a href=
"../Server-security/" class=
"btn btn-neutral float-right" title=
"Server security">Next
<span class=
"icon icon-circle-arrow-right"></span></a>
709 <a href=
"../Server-requirements/" class=
"btn btn-neutral" title=
"Server requirements"><span class=
"icon icon-circle-arrow-left"></span> Previous
</a>
716 <div role=
"contentinfo">
717 <!-- Copyright etc -->
721 Built with
<a href=
"http://www.mkdocs.org">MkDocs
</a> using a
<a href=
"https://github.com/snide/sphinx_rtd_theme">theme
</a> provided by
<a href=
"https://readthedocs.org">Read the Docs
</a>.
731 <div class=
"rst-versions" role=
"note" style=
"cursor: pointer">
732 <span class=
"rst-current-version" data-toggle=
"rst-current-version">
734 <a href=
"https://github.com/shaarli/Shaarli" class=
"fa fa-github" style=
"float: left; color: #fcfcfc"> GitHub
</a>
737 <span><a href=
"../Server-requirements/" style=
"color: #fcfcfc;">« Previous
</a></span>
740 <span style=
"margin-left: 15px"><a href=
"../Server-security/" style=
"color: #fcfcfc">Next
»</a></span>
744 <script src=
"../js/theme.js"></script>