aboutsummaryrefslogtreecommitdiffhomepage
path: root/doc/md/Server-configuration.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/md/Server-configuration.md')
-rw-r--r--doc/md/Server-configuration.md644
1 files changed, 324 insertions, 320 deletions
diff --git a/doc/md/Server-configuration.md b/doc/md/Server-configuration.md
index 88eed8e6..297d7c29 100644
--- a/doc/md/Server-configuration.md
+++ b/doc/md/Server-configuration.md
@@ -1,20 +1,46 @@
1# Server configuration
1 2
2- [Prerequisites](#prerequisistes) 3## Requirements
3- [Apache](#apache)
4- [Nginx](#nginx)
5- [Proxies](#proxies)
6- [See also](#see-also)
7 4
8## Prerequisites 5### Operating system and web server
9### Shaarli
10 6
11- A web server and PHP interpreter module/service have been installed. 7Shaarli can be hosted on dedicated/virtual servers, or shared hosting.
12- You have write access to the Shaarli installation directory. 8
13- The correct read/write permissions have been granted to the web server user and group. 9You need write access to the Shaarli installation directory - you should have received instructions from your hosting provider on how to connect to the server using SSH (or FTP for shared hosts).
14- Your PHP interpreter is compatible with supported PHP versions: 10
11Examples in this documentation are given for [Debian](https://www.debian.org/), a GNU/Linux distribution widely used in server environments. Please adapt them to your specific Linux distribution.
12
13A $5/month VPS (1 CPU, 1 GiB RAM and 25 GiB SSD) will run any Shaarli installation without problems. Some hosting providers: [DigitalOcean](https://www.digitalocean.com/) ([1](https://www.digitalocean.com/docs/droplets/overview/), [2](https://www.digitalocean.com/pricing/), [3](https://www.digitalocean.com/docs/droplets/how-to/create/), [4](https://www.digitalocean.com/docs/droplets/how-to/add-ssh-keys/), [5](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-debian-8), [6](https://www.digitalocean.com/community/tutorials/an-introduction-to-securing-your-linux-vps)), [Gandi](https://www.gandi.net/en), [OVH](https://www.ovh.co.uk/), [RackSpace](https://www.rackspace.com/), etc.
14
15
16### Network and domain name
17
18Try to host the server in a region that is geographically close to your users.
19
20A **domain name** ([DNS record](https://opensource.com/article/17/4/introduction-domain-name-system-dns)) pointing to the server's public IP address is required to obtain a SSL/TLS certificate and setup HTTPS to secure client traffic to your Shaarli instance.
21
22You can obtain a domain name from a [registrar](https://en.wikipedia.org/wiki/Domain_name_registrar) ([1](https://www.ovh.co.uk/domains), [2](https://www.gandi.net/en/domain)), or from free subdomain providers ([1](https://freedns.afraid.org/)). If you don't have a domain name, please set up a private domain name ([FQDN](ttps://en.wikipedia.org/wiki/Fully_qualified_domain_name)) in your clients' [hosts files](https://en.wikipedia.org/wiki/Hosts_(file)) to access the server (direct access by IP address can result in unexpected behavior).
23
24Setup a **firewall** (using `iptables`, [ufw](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-debian-10), [fireHOL](https://firehol.org/) or any frontend of your choice) to deny all incoming traffic except `tcp/80` and `tcp/443`, which are needed to access the web server (and any other posrts you might need, like SSH). If the server is in a private network behind a NAT, ensure these **ports are forwarded** to the server.
25
26Shaarli makes outbound HTTP/HTTPS connections to websites you bookmark to fetch page information (title, thumbnails), the server must then have access to the Internet as well, and a working DNS resolver.
27
28
29### Screencast
30
31Here is a screencast of the installation procedure
32
33[![asciicast](https://asciinema.org/a/z3RXxcJIRgWk0jM2ws6EnUFgO.svg)](https://asciinema.org/a/z3RXxcJIRgWk0jM2ws6EnUFgO)
34
35--------------------------------------------------------------------------------
36
37### PHP
38
39Supported PHP versions:
15 40
16Version | Status | Shaarli compatibility 41Version | Status | Shaarli compatibility
17:---:|:---:|:---: 42:---:|:---:|:---:
437.3 | Supported | Yes
187.2 | Supported | Yes 447.2 | Supported | Yes
197.1 | Supported | Yes 457.1 | Supported | Yes
207.0 | EOL: 2018-12-03 | Yes (up to Shaarli 0.10.x) 467.0 | EOL: 2018-12-03 | Yes (up to Shaarli 0.10.x)
@@ -23,71 +49,132 @@ Version | Status | Shaarli compatibility
235.4 | EOL: 2015-09-14 | Yes (up to Shaarli 0.8.x) 495.4 | EOL: 2015-09-14 | Yes (up to Shaarli 0.8.x)
245.3 | EOL: 2014-08-14 | Yes (up to Shaarli 0.8.x) 505.3 | EOL: 2014-08-14 | Yes (up to Shaarli 0.8.x)
25 51
26- The following PHP extensions are installed on the server: 52Required PHP extensions:
27 53
28Extension | Required? | Usage 54Extension | Required? | Usage
29---|:---:|--- 55---|:---:|---
30[`openssl`](http://php.net/manual/en/book.openssl.php) | All | OpenSSL, HTTPS 56[`openssl`](http://php.net/manual/en/book.openssl.php) | requires | OpenSSL, HTTPS
57[`php-json`](http://php.net/manual/en/book.json.php) | required | configuration parsing
58[`php-simplexml`](https://www.php.net/manual/en/book.simplexml.php) | required | REST API (Slim framework)
31[`php-mbstring`](http://php.net/manual/en/book.mbstring.php) | CentOS, Fedora, RHEL, Windows, some hosting providers | multibyte (Unicode) string support 59[`php-mbstring`](http://php.net/manual/en/book.mbstring.php) | CentOS, Fedora, RHEL, Windows, some hosting providers | multibyte (Unicode) string support
32[`php-gd`](http://php.net/manual/en/book.image.php) | optional | required to use thumbnails 60[`php-gd`](http://php.net/manual/en/book.image.php) | optional | required to use thumbnails
33[`php-intl`](http://php.net/manual/en/book.intl.php) | optional | localized text sorting (e.g. `e->è->f`) 61[`php-intl`](http://php.net/manual/en/book.intl.php) | optional | localized text sorting (e.g. `e->è->f`)
34[`php-curl`](http://php.net/manual/en/book.curl.php) | optional | using cURL for fetching webpages and thumbnails in a more robust way 62[`php-curl`](http://php.net/manual/en/book.curl.php) | optional | using cURL for fetching webpages and thumbnails in a more robust way
35[`php-gettext`](http://php.net/manual/en/book.gettext.php) | optional | Use the translation system in gettext mode (faster) 63[`php-gettext`](http://php.net/manual/en/book.gettext.php) | optional | Use the translation system in gettext mode (faster)
36 64
37-------------------------------------------------------------------------------- 65Some [plugins](Plugins.md) may require additional configuration.
66
67- [PHP: Supported versions](http://php.net/supported-versions.php)
68- [PHP: Unsupported versions (EOL/End-of-life)](http://php.net/eol.php)
69- [PHP 7 Changelog](http://php.net/ChangeLog-7.php)
70- [PHP 5 Changelog](http://php.net/ChangeLog-5.php)
71- [PHP: Bugs](https://bugs.php.net/)
38 72
39### SSL/TLS configuration
40 73
41To setup HTTPS / SSL on your webserver (recommended), you must generate a public/private **key pair** and a **certificate**, and install, configure and activate the appropriate **webserver SSL extension**. 74## SSL/TLS (HTTPS)
42 75
43#### Let's Encrypt 76We recommend setting up [HTTPS](https://en.wikipedia.org/wiki/HTTPS) (SSL/[TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security)) on your webserver for secure communication between clients and the server.
44 77
45[Let's Encrypt](https://en.wikipedia.org/wiki/Let%27s_Encrypt) is a certificate authority that provides free TLS/X.509 certificates via an automated process. 78### Let's Encrypt
46 79
47 * Install `certbot` using the appropriate method described on https://certbot.eff.org/. 80For public-facing web servers this can be done using free SSL/TLS certificates from [Let's Encrypt](https://en.wikipedia.org/wiki/Let's_Encrypt), a non-profit certificate authority provididing free certificates.
48
49Location of the `certbot` program and template configuration files may vary depending on which installation method was used. Change the file paths below accordingly. Here is an easy way to create a signed certificate using `certbot`, it assumes `certbot` was installed through APT on a Debian-based distribution:
50 81
51 * Stop the apache2/nginx service. 82 - [How to secure Apache with Let's Encrypt](https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-debian-10)
52 * Run `certbot --agree-tos --standalone --preferred-challenges tls-sni --email "youremail@example.com" --domain yourdomain.example.com` 83 - [How to secure Nginx with Let's Encrypt](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-debian-10)
53 * For the Apache webserver, copy `/usr/lib/python2.7/dist-packages/certbot_apache/options-ssl-apache.conf` to `/etc/letsencrypt/options-ssl-apache.conf` (paths may vary depending on installation method) 84 - [How To Use Certbot Standalone Mode to Retrieve Let's Encrypt SSL Certificates](https://www.digitalocean.com/community/tutorials/how-to-use-certbot-standalone-mode-to-retrieve-let-s-encrypt-ssl-certificates-on-debian-10).
54 * For Nginx: TODO
55 * Setup your webserver as described below
56 * Restart the apache2/nginx service.
57 85
58#### Self-signed certificates 86In short:
59 87
60If you don't want to request a certificate from Let's Encrypt, or are unable to (for example, webserver on a LAN, or domain name not registered in the public DNS system), you can generate a self-signed certificate. This certificate will trigger security warnings in web browsers, unless you add it to the browser's SSL store manually. 88```bash
89# install certbot
90sudo apt install certbot
61 91
62* Apache: run `make-ssl-cert generate-default-snakeoil --force-overwrite` 92# stop your webserver if you already have one running
63* Nginx: TODO 93# certbot in standalone mode needs to bind to port 80 (only needed on initial generation)
94sudo systemctl stop apache2
95sudo systemctl stop nginx
96
97# generate initial certificates
98# Let's Encrypt ACME servers must be able to access your server! port forwarding and firewall must be properly configured
99sudo certbot certonly --standalone --noninteractive --agree-tos --email "admin@shaarli.mydomain.org" -d shaarli.mydomain.org
100# this will generate a private key and certificate at /etc/letsencrypt/live/shaarli.mydomain.org/{privkey,fullchain}.pem
101
102# restart the web server
103sudo systemctl start apache2
104sudo systemctl start nginx
105```
106
107On apache `2.4.43+`, you can also delegate LE certificate management to [mod_md](https://httpd.apache.org/docs/2.4/mod/mod_md.html) [[1](https://www.cyberciti.biz/faq/how-to-secure-apache-with-mod_md-lets-encrypt-on-ubuntu-20-04-lts/)] in which case you don't need certbot and manual SSL configuration in virtualhosts.
108
109### Self-signed
110
111If you don't want to rely on a certificate authority, or the server can only be accessed from your own network, you can also generate self-signed certificates. Not that this will generate security warnings in web browsers/clients trying to access Shaarli:
112
113- [How To Create a Self-Signed SSL Certificate for Apache](https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-apache-on-debian-10)
114- [How To Create a Self-Signed SSL Certificate for Nginx](https://www.digitalocean.com/community/tutorials/how-to-create-a-self-signed-ssl-certificate-for-nginx-on-debian-10)
115- [How to Create Self-Signed SSL Certificates with OpenSSL](http://www.xenocafe.com/tutorials/linux/centos/openssl/self_signed_certificates/index.php)
116- [How do I create my own Certificate Authority?](https://workaround.org/certificate-authority)
64 117
65-------------------------------------------------------------------------------- 118--------------------------------------------------------------------------------
66 119
67## Apache 120## Examples
121
122The following examples assume a Debian-based operating system is installed. On other distributions you may have to adapt details such as package installation procedures, configuration file locations, and webserver username/group (`www-data` or `httpd` are common values). In these examples we assume the document root for your web server/virtualhost is at `/var/www/shaarli.mydomain.org/`:
123
124```bash
125# create the document root (replace with your own domain name)
126sudo mkdir -p /var/www/shaarli.mydomain.org/
127```
128
129You can install Shaarli at the root of your virtualhost, or in a subdirectory as well. See [Directory structure](Directory-structure)
68 130
69Here is a basic configuration example for the Apache web server with `mod_php`.
70 131
71In `/etc/apache2/sites-available/shaarli.conf`: 132### Apache
133
134```bash
135# Install apache + mod_php and PHP modules
136sudo apt update
137sudo apt install apache2 libapache2-mod-php php-json php-mbstring php-gd php-intl php-curl php-gettext
138
139# Edit the virtualhost configuration file with your favorite editor (replace the example domain name)
140sudo nano /etc/apache2/sites-available/shaarli.mydomain.org.conf
141```
72 142
73```apache 143```apache
74<VirtualHost *:443> 144<VirtualHost *:80>
75 ServerName shaarli.my-domain.org 145 ServerName shaarli.mydomain.org
76 DocumentRoot /absolute/path/to/shaarli/ 146 DocumentRoot /var/www/shaarli.mydomain.org/
147
148 # For SSL/TLS certificates acquired with certbot or self-signed certificates
149 # Redirect HTTP requests to HTTPS, except Let's Encrypt ACME challenge requests
150 RewriteEngine on
151 RewriteRule ^.well-known/acme-challenge/ - [L]
152 RewriteCond %{HTTP_HOST} =shaarli.mydomain.org
153 RewriteRule ^ https://shaarli.mydomain.org%{REQUEST_URI} [END,NE,R=permanent]
154</VirtualHost>
77 155
78 # Logging 156# SSL/TLS configuration for Let's Encrypt certificates managed with mod_md
79 # Possible values include: debug, info, notice, warn, error, crit, alert, emerg. 157#MDomain shaarli.mydomain.org
80 LogLevel warn 158#MDCertificateAgreement accepted
81 ErrorLog /var/log/apache2/shaarli-error.log 159#MDContactEmail admin@shaarli.mydomain.org
82 CustomLog /var/log/apache2/shaarli-access.log combined 160#MDPrivateKeys RSA 4096
83 161
84 # Let's Encrypt SSL configuration (recommended) 162<VirtualHost *:443>
85 SSLEngine on 163 ServerName shaarli.mydomain.org
86 SSLCertificateFile /etc/letsencrypt/live/yourdomain.example.com/fullchain.pem 164 DocumentRoot /var/www/shaarli.mydomain.org/
87 SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.example.com/privkey.pem
88 Include /etc/letsencrypt/options-ssl-apache.conf
89 165
90 # Self-signed SSL cert configuration 166 # SSL/TLS configuration for Let's Encrypt certificates acquired with certbot standalone
167 SSLEngine on
168 SSLCertificateFile /etc/letsencrypt/live/shaarli.mydomain.org/fullchain.pem
169 SSLCertificateKeyFile /etc/letsencrypt/live/shaarli.mydomain.org/privkey.pem
170 # Let's Encrypt settings from https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/tls_configs/current-options-ssl-apache.conf
171 SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
172 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
173 SSLHonorCipherOrder off
174 SSLSessionTickets off
175 SSLOptions +StrictRequire
176
177 # SSL/TLS configuration for self-signed certificates
91 #SSLEngine on 178 #SSLEngine on
92 #SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem 179 #SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
93 #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key 180 #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
@@ -98,345 +185,262 @@ In `/etc/apache2/sites-available/shaarli.conf`:
98 #php_value error_reporting 2147483647 185 #php_value error_reporting 2147483647
99 #php_value error_log /var/log/apache2/shaarli-php-error.log 186 #php_value error_log /var/log/apache2/shaarli-php-error.log
100 187
101 <Directory /absolute/path/to/shaarli/> 188 <Directory /var/www/shaarli.mydomain.org/>
102 #Required for .htaccess support 189 # Required for .htaccess support
103 AllowOverride All 190 AllowOverride All
104 Order allow,deny 191 Require all granted
105 Allow from all
106
107 Options Indexes FollowSymLinks MultiViews #TODO is Indexes/Multiviews required?
108
109 # Optional - required for playvideos plugin
110 #Header set Content-Security-Policy "script-src 'self' 'unsafe-inline' https://www.youtube.com https://s.ytimg.com 'unsafe-eval'"
111 </Directory> 192 </Directory>
112 193
113</VirtualHost> 194 <LocationMatch "/\.">
114``` 195 # Prevent accessing dotfiles
115 196 RedirectMatch 404 ".*"
116Enable this configuration with `sudo a2ensite shaarli` 197 </LocationMatch>
117
118_Note: If you use Apache 2.2 or lower, you need [mod_version](https://httpd.apache.org/docs/current/mod/mod_version.html) to be installed and enabled._
119 198
120_Note: Apache module `mod_rewrite` must be enabled to use the REST API._ 199 <LocationMatch "\.(?:ico|css|js|gif|jpe?g|png)$">
200 # allow client-side caching of static files
201 Header set Cache-Control "max-age=2628000, public, must-revalidate, proxy-revalidate"
202 </LocationMatch>
121 203
204 # serve the Shaarli favicon from its custom location
205 Alias favicon.ico /var/www/shaarli.mydomain.org/images/favicon.ico
122 206
123## Nginx 207</VirtualHost>
208```
124 209
125Here is a basic configuration example for the Nginx web server, using the [php-fpm](http://php-fpm.org) PHP FastCGI Process Manager, and Nginx's [FastCGI](https://en.wikipedia.org/wiki/FastCGI) module. 210```bash
211# Enable the virtualhost
212sudo a2ensite shaarli.mydomain.org
126 213
127<!--- TODO refactor everything below this point ---> 214# mod_ssl must be enabled to use TLS/SSL certificates
215# https://httpd.apache.org/docs/current/mod/mod_ssl.html
216sudo a2enmod ssl
128 217
129### Common setup 218# mod_rewrite must be enabled to use the REST API
130Once Nginx and PHP-FPM are installed, we need to ensure: 219# https://httpd.apache.org/docs/current/mod/mod_rewrite.html
220sudo a2enmod rewrite
131 221
132- Nginx and PHP-FPM are running using the _same user and group_ 222# mod_headers must be enabled to set custom headers from the server config
133- both these user and group have 223sudo a2enmod headers
134 - `read` permissions for Shaarli resources
135 - `execute` permissions for Shaarli directories _AND_ their parent directories
136 224
137On a production server: 225# mod_version must only be enabled if you use Apache 2.2 or lower
226# https://httpd.apache.org/docs/current/mod/mod_version.html
227# sudo a2enmod version
138 228
139- `user:group` will likely be `http:http`, `www:www` or `www-data:www-data` 229# restart the apache service
140- files will be located under `/var/www`, `/var/http` or `/usr/share/nginx` 230sudo systemctl restart apache2
231```
141 232
142On a development server: 233- [How to install the Apache web server](https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-debian-10)
234- [Apache/PHP - error log per VirtualHost - StackOverflow](http://stackoverflow.com/q/176)
235- [Apache - PHP: php_value vs php_admin_value and the use of php_flag explained](https://ma.ttias.be/php-php_value-vs-php_admin_value-and-the-use-of-php_flag-explained/)
236- [Server-side TLS (Apache) - Mozilla](https://wiki.mozilla.org/Security/Server_Side_TLS#Apache)
237- [Apache 2.4 documentation](https://httpd.apache.org/docs/2.4/)
238- [Apache mod_proxy](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html)
239- [Apache Reverse Proxy Request Headers](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#x-headers)
143 240
144- files may be located in a user's home directory
145- in this case, make sure both Nginx and PHP-FPM are running as the local user/group!
146 241
147For all following configuration examples, this user/group pair will be used: 242### Nginx
148 243
149- `user:group = john:users`, 244This examples uses nginx and the [PHP-FPM](https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mariadb-php-lemp-stack-on-debian-10#step-3-%E2%80%94-installing-php-for-processing) PHP interpreter. Nginx and PHP-FPM must be running using the same user and group, here we assume the user/group to be `www-data:www-data`.
150 245
151which corresponds to the following service configuration:
152 246
153```ini 247```bash
154; /etc/php/php-fpm.conf 248# install nginx and php-fpm
155user = john 249sudo apt update
156group = users 250sudo apt install nginx php-fpm
157 251
158[...] 252# Edit the virtualhost configuration file with your favorite editor
159listen.owner = john 253sudo nano /etc/nginx/sites-available/shaarli.mydomain.org
160listen.group = users
161``` 254```
162 255
163```nginx 256```nginx
164# /etc/nginx/nginx.conf 257server {
165user john users; 258 listen 80;
259 server_name shaarli.mydomain.org;
166 260
167http { 261 # redirect all plain HTTP requests to HTTPS
168 [...] 262 return 301 https://shaarli.mydomain.org$request_uri;
169} 263}
170```
171
172### (Optional) Increase the maximum file upload size
173Some bookmark dumps generated by web browsers can be _huge_ due to the presence of Base64-encoded images and favicons, as well as extra verbosity when nesting links in (sub-)folders.
174
175To increase upload size, you will need to modify both nginx and PHP configuration:
176
177```nginx
178# /etc/nginx/nginx.conf
179
180http {
181 [...]
182
183 client_max_body_size 10m;
184
185 [...]
186}
187```
188
189```ini
190# /etc/php5/fpm/php.ini
191
192[...]
193post_max_size = 10M
194[...]
195upload_max_filesize = 10M
196```
197 264
198### Minimal 265server {
199_WARNING: Use for development only!_ 266 # ipv4 listening port/protocol
200 267 listen 443 ssl http2;
201```nginx 268 # ipv6 listening port/protocol
202user john users; 269 listen [::]:443 ssl http2;
203worker_processes 1; 270 server_name shaarli.mydomain.org;
204events { 271 root /var/www/shaarli.mydomain.org;
205 worker_connections 1024; 272
206} 273 # log file locations
274 # combined log format prepends the virtualhost/domain name to log entries
275 access_log /var/log/nginx/access.log combined;
276 error_log /var/log/nginx/error.log;
207 277
208http { 278 # paths to private key and certificates for SSL/TLS
209 include mime.types; 279 ssl_certificate /etc/ssl/shaarli.mydomain.org.crt;
210 default_type application/octet-stream; 280 ssl_certificate_key /etc/ssl/private/shaarli.mydomain.org.key;
211 keepalive_timeout 20; 281
212 282 # Let's Encrypt SSL settings from https://github.com/certbot/certbot/blob/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf
213 index index.html index.php; 283 ssl_session_cache shared:le_nginx_SSL:10m;
214 284 ssl_session_timeout 1440m;
215 server { 285 ssl_session_tickets off;
216 listen 80; 286 ssl_protocols TLSv1.2 TLSv1.3;
217 server_name localhost; 287 ssl_prefer_server_ciphers off;
218 root /home/john/web; 288 ssl_ciphers "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";
219 289
220 access_log /var/log/nginx/access.log; 290 # increase the maximum file upload size if needed: by default nginx limits file upload to 1MB (413 Entity Too Large error)
221 error_log /var/log/nginx/error.log; 291 client_max_body_size 100m;
222 292
223 location /shaarli/ { 293 # relative path to shaarli from the root of the webserver
224 try_files $uri /shaarli/index.php$is_args$args; 294 location / {
225 access_log /var/log/nginx/shaarli.access.log; 295 # default index file when no file URI is requested
226 error_log /var/log/nginx/shaarli.error.log; 296 index index.php;
227 } 297 try_files $uri /index.php$is_args$args;
228
229 location ~ (index)\.php$ {
230 try_files $uri =404;
231 fastcgi_split_path_info ^(.+\.php)(/.+)$;
232 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
233 fastcgi_index index.php;
234 include fastcgi.conf;
235 }
236 } 298 }
237}
238```
239 299
240### Modular 300 location ~ (index)\.php$ {
241The previous setup is sufficient for development purposes, but has several major caveats: 301 try_files $uri =404;
302 # slim API - split URL path into (script_filename, path_info)
303 fastcgi_split_path_info ^(.+\.php)(/.+)$;
304 # pass PHP requests to PHP-FPM
305 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
306 fastcgi_index index.php;
307 include fastcgi.conf;
308 }
242 309
243- every content that does not match the PHP rule will be sent to client browsers: 310 location ~ \.php$ {
244 - dotfiles - in our case, `.htaccess` 311 # deny access to all other PHP scripts
245 - temporary files, e.g. Vim or Emacs files: `index.php~` 312 # disable this if you host other PHP applications on the same virtualhost
246- asset / static resource caching is not optimized 313 deny all;
247- if serving several PHP sites, there will be a lot of duplication: `location /shaarli/`, `location /mysite/`, etc. 314 }
248 315
249To solve this, we will split Nginx configuration in several parts, that will be included when needed: 316 location ~ /\. {
317 # deny access to dotfiles
318 deny all;
319 }
250 320
251```nginx 321 location ~ ~$ {
252# /etc/nginx/deny.conf 322 # deny access to temp editor files, e.g. "script.php~"
253location ~ /\. { 323 deny all;
254 # deny access to dotfiles 324 }
255 access_log off;
256 log_not_found off;
257 deny all;
258}
259 325
260location ~ ~$ { 326 location = /favicon.ico {
261 # deny access to temp editor files, e.g. "script.php~" 327 # serve the Shaarli favicon from its custom location
262 access_log off; 328 alias /var/www/shaarli/images/favicon.ico;
263 log_not_found off; 329 }
264 deny all;
265}
266```
267 330
268```nginx 331 # allow client-side caching of static files
269# /etc/nginx/php.conf 332 location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
270location ~ (index)\.php$ { 333 expires max;
271 # Slim - split URL path into (script_filename, path_info) 334 add_header Cache-Control "public, must-revalidate, proxy-revalidate";
272 try_files $uri =404; 335 # HTTP 1.0 compatibility
273 fastcgi_split_path_info ^(.+\.php)(/.+)$; 336 add_header Pragma public;
274 337 }
275 # filter and proxy PHP requests to PHP-FPM
276 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
277 fastcgi_index index.php;
278 include fastcgi.conf;
279}
280 338
281location ~ \.php$ {
282 # deny access to all other PHP scripts
283 deny all;
284} 339}
285``` 340```
286 341
287```nginx 342```bash
288# /etc/nginx/static_assets.conf 343# enable the configuration/virtualhost
289location ~* \.(?:ico|css|js|gif|jpe?g|png)$ { 344sudo ln -s /etc/nginx/sites-available/shaarli.mydomain.org /etc/nginx/sites-enabled/shaarli.mydomain.org
290 expires max; 345# reload nginx configuration
291 add_header Pragma public; 346sudo systemctl reload nginx
292 add_header Cache-Control "public, must-revalidate, proxy-revalidate";
293}
294``` 347```
295 348
296```nginx 349- [How to install the Nginx web server](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-debian-10)
297# /etc/nginx/nginx.conf 350- [Nginx Beginner's guide](http://nginx.org/en/docs/beginners_guide.html)
298[...] 351- [Nginx documentation](https://nginx.org/en/docs/)
299 352- [Nginx ngx_http_fastcgi_module](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html)
300http { 353- [Nginx Pitfalls](http://wiki.nginx.org/Pitfalls)
301 [...] 354- [Nginx PHP configuration examples - Karl Blessing](http://kbeezie.com/nginx-configuration-examples/)
302 355- [Server-side TLS (Nginx) - Mozilla](https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx)
303 root /home/john/web;
304 access_log /var/log/nginx/access.log;
305 error_log /var/log/nginx/error.log;
306 356
307 server {
308 # virtual host for a first domain
309 listen 80;
310 server_name my.first.domain.org;
311 357
312 location /shaarli/ {
313 # Slim - rewrite URLs
314 try_files $uri /shaarli/index.php$is_args$args;
315 358
316 access_log /var/log/nginx/shaarli.access.log; 359## Reverse proxies
317 error_log /var/log/nginx/shaarli.error.log;
318 }
319 360
320 location = /shaarli/favicon.ico { 361If Shaarli is hosted on a server behind a [reverse proxy](https://en.wikipedia.org/wiki/Reverse_proxy) (i.e. there is a proxy server between clients and the web server hosting Shaarli), configure it accordingly. See [Reverse proxy](Reverse-proxy.md) configuration.
321 # serve the Shaarli favicon from its custom location
322 alias /var/www/shaarli/images/favicon.ico;
323 }
324 362
325 include deny.conf;
326 include static_assets.conf;
327 include php.conf;
328 }
329 363
330 server {
331 # virtual host for a second domain
332 listen 80;
333 server_name second.domain.com;
334 364
335 location /minigal/ { 365## Allow import of large browser bookmarks export
336 access_log /var/log/nginx/minigal.access.log;
337 error_log /var/log/nginx/minigal.error.log;
338 }
339 366
340 include deny.conf; 367Web browser bookmark exports can be large due to the presence of base64-encoded images and favicons/long subfolder names. Edit the PHP configuration file.
341 include static_assets.conf;
342 include php.conf;
343 }
344}
345```
346 368
347### Redirect HTTP to HTTPS 369- Apache: `/etc/php/<PHP_VERSION>/apache2/php.ini`
348Assuming you have generated a (self-signed) key and certificate, and they are 370- Nginx + PHP-FPM: `/etc/php/<PHP_VERSION>/fpm/php.ini` (in addition to `client_max_body_size` in the [Nginx configuration](#nginx))
349located under `/home/john/ssl/localhost.{key,crt}`, it is pretty straightforward
350to set an HTTP (:80) to HTTPS (:443) redirection to force SSL/TLS usage.
351 371
352```nginx 372```ini
353# /etc/nginx/nginx.conf
354[...] 373[...]
374# (optional) increase the maximum file upload size:
375post_max_size = 100M
376[...]
377# (optional) increase the maximum file upload size:
378upload_max_filesize = 100M
379```
355 380
356http { 381To verify PHP settings currently set on the server, create a `phpinfo.php` in your webserver's document root
357 [...]
358
359 index index.html index.php;
360
361 root /home/john/web;
362 access_log /var/log/nginx/access.log;
363 error_log /var/log/nginx/error.log;
364
365 server {
366 listen 80;
367 server_name localhost;
368 382
369 return 301 https://localhost$request_uri; 383```bash
370 } 384# example
385echo '<?php phpinfo(); ?>' | sudo tee /var/www/shaarli.mydomain.org/phpinfo.php
386#give read-only access to this file to the webserver user
387sudo chown www-data:root /var/www/shaarli.mydomain.org/phpinfo.php
388sudo chmod 0400 /var/www/shaarli.mydomain.org/phpinfo.php
389```
371 390
372 server { 391Access the file from a web browser (eg. <https://shaarli.mydomain.org/phpinfo.php> and look at the _Loaded Configuration File_ and _Scan this dir for additional .ini files_ entries
373 listen 443 ssl;
374 server_name localhost;
375 392
376 ssl_certificate /home/john/ssl/localhost.crt; 393It is recommended to remove the `phpinfo.php` when no longer needed as it publicly discloses details about your webserver configuration.
377 ssl_certificate_key /home/john/ssl/localhost.key;
378 394
379 location /shaarli/ {
380 # Slim - rewrite URLs
381 try_files $uri /index.php$is_args$args;
382 395
383 access_log /var/log/nginx/shaarli.access.log; 396## Robots and crawlers
384 error_log /var/log/nginx/shaarli.error.log;
385 }
386 397
387 location = /shaarli/favicon.ico { 398To opt-out of indexing your Shaarli instance by search engines, create a `robots.txt` file at the root of your virtualhost:
388 # serve the Shaarli favicon from its custom location
389 alias /var/www/shaarli/images/favicon.ico;
390 }
391 399
392 include deny.conf; 400```
393 include static_assets.conf; 401User-agent: *
394 include php.conf; 402Disallow: /
395 }
396}
397``` 403```
398 404
399## Proxies 405By default Shaarli already disallows indexing of your local copy of the documentation by default, using `<meta name="robots">` HTML tags. Your Shaarli instance may still be indexed by various robots on the public Internet, that do not respect this header or the robots standard.
400
401If 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:
402 406
403- `X-Forwarded-Proto` 407- [Robots exclusion standard](https://en.wikipedia.org/wiki/Robots_exclusion_standard)
404- `X-Forwarded-Host` 408- [Introduction to robots.txt](https://support.google.com/webmasters/answer/6062608?hl=en)
405- `X-Forwarded-For` 409- [Robots meta tag, data-nosnippet, and X-Robots-Tag specifications](https://developers.google.com/search/reference/robots_meta_tag)
410- [About robots.txt](http://www.robotstxt.org)
411- [About the robots META tag](https://www.robotstxt.org/meta.html)
406 412
407In you [Shaarli configuration](Shaarli-configuration) `data/config.json.php`, add the public IP of your proxy under `security.trusted_proxies`.
408 413
409See also [proxy-related](https://github.com/shaarli/Shaarli/issues?utf8=%E2%9C%93&q=label%3Aproxy+) issues. 414## Fail2ban
410 415
411## Robots and crawlers 416[fail2ban](http://www.fail2ban.org/wiki/index.php/Main_Page) is an intrusion prevention framework that reads server (Apache, SSH, etc.) and uses `iptables` profiles to block brute-force attempts. You need to create a filter to detect shaarli login failures in logs, and a jail configuation to configure the behavior when failed login attempts are detected:
412 417
413Shaarli disallows indexing and crawling of your local documentation pages by search engines, using `<meta name="robots">` HTML tags. 418```ini
414Your Shaarli instance and other pages you host may still be indexed by various robots on the public Internet. 419# /etc/fail2ban/filter.d/shaarli-auth.conf
415You may want to setup a robots.txt file or other crawler control mechanism on your server. 420[INCLUDES]
416See [[1]](https://en.wikipedia.org/wiki/Robots_exclusion_standard), [[2]](https://support.google.com/webmasters/answer/6062608?hl=en) and [[3]](https://developers.google.com/search/reference/robots_meta_tag) 421before = common.conf
422[Definition]
423failregex = \s-\s<HOST>\s-\sLogin failed for user.*$
424ignoreregex =
425```
417 426
418## See also 427```ini
428# /etc/fail2ban/jail.local
429[shaarli-auth]
430enabled = true
431port = https,http
432filter = shaarli-auth
433logpath = /var/www/shaarli.mydomain.org/data/log.txt
434# allow 3 login attempts per IP address
435# (over a period specified by findtime = in /etc/fail2ban/jail.conf)
436maxretry = 3
437# permanently ban the IP address after reaching the limit
438bantime = -1
439```
419 440
420 * [Server security](Server-security.md) 441Then restart the service: `sudo systemctl restart fail2ban`
421 442
422#### Webservers
423 443
424- [Apache/PHP - error log per VirtualHost](http://stackoverflow.com/q/176) (StackOverflow) 444## What next?
425- [Apache - PHP: php_value vs php_admin_value and the use of php_flag explained](https://ma.ttias.be/php-php_value-vs-php_admin_value-and-the-use-of-php_flag-explained/)
426- [Server-side TLS (Apache)](https://wiki.mozilla.org/Security/Server_Side_TLS#Apache) (Mozilla)
427- [Nginx Beginner's guide](http://nginx.org/en/docs/beginners_guide.html)
428- [Nginx ngx_http_fastcgi_module](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html)
429- [Nginx Pitfalls](http://wiki.nginx.org/Pitfalls)
430- [Nginx PHP configuration examples](http://kbeezie.com/nginx-configuration-examples/) (Karl Blessing)
431- [Server-side TLS (Nginx)](https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx) (Mozilla)
432- [How to Create Self-Signed SSL Certificates with OpenSSL](http://www.xenocafe.com/tutorials/linux/centos/openssl/self_signed_certificates/index.php)
433- [How do I create my own Certificate Authority?](https://workaround.org/certificate-authority)
434
435#### PHP
436 445
437- [Travis configuration](https://github.com/shaarli/Shaarli/blob/master/.travis.yml) 446[Shaarli installation](Installation.md)
438- [PHP: Supported versions](http://php.net/supported-versions.php)
439- [PHP: Unsupported versions](http://php.net/eol.php) _(EOL - End Of Life)_
440- [PHP 7 Changelog](http://php.net/ChangeLog-7.php)
441- [PHP 5 Changelog](http://php.net/ChangeLog-5.php)
442- [PHP: Bugs](https://bugs.php.net/)