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 f9ea2ed2..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,420 +49,398 @@ 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
31[`php-json`](http://php.net/manual/en/book.json.php) | required | configuration parsing 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)
32[`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
33[`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
34[`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`)
35[`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
36[`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)
37--------------------------------------------------------------------------------
38
39### SSL/TLS configuration
40 64
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**. 65Some [plugins](Plugins.md) may require additional configuration.
42 66
43#### Let's Encrypt 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/)
44 72
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.
46 73
47 * Install `certbot` using the appropriate method described on https://certbot.eff.org/. 74## SSL/TLS (HTTPS)
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 75
51 * Stop the apache2/nginx service. 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.
52 * Run `certbot --agree-tos --standalone --preferred-challenges tls-sni --email "youremail@example.com" --domain yourdomain.example.com`
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)
54 * For Nginx: TODO
55 * Setup your webserver as described below
56 * Restart the apache2/nginx service.
57 77
58#### Self-signed certificates 78### Let's Encrypt
59 79
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. 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.
61 81
62* Apache: run `make-ssl-cert generate-default-snakeoil --force-overwrite` 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)
63* Nginx: TODO 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)
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).
64 85
65-------------------------------------------------------------------------------- 86In short:
66 87
67## Apache 88```bash
89# install certbot
90sudo apt install certbot
68 91
69Here is a basic configuration example for the Apache web server with `mod_php`. 92# stop your webserver if you already have one running
93# certbot in standalone mode needs to bind to port 80 (only needed on initial generation)
94sudo systemctl stop apache2
95sudo systemctl stop nginx
70 96
71In `/etc/apache2/sites-available/shaarli.conf`: 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
72 101
73```apache 102# restart the web server
74<VirtualHost *:443> 103sudo systemctl start apache2
75 ServerName shaarli.my-domain.org 104sudo systemctl start nginx
76 DocumentRoot /absolute/path/to/shaarli/ 105```
77 106
78 # Logging 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.
79 # Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
80 LogLevel warn
81 ErrorLog /var/log/apache2/shaarli-error.log
82 CustomLog /var/log/apache2/shaarli-access.log combined
83 108
84 # Let's Encrypt SSL configuration (recommended) 109### Self-signed
85 SSLEngine on
86 SSLCertificateFile /etc/letsencrypt/live/yourdomain.example.com/fullchain.pem
87 SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.example.com/privkey.pem
88 Include /etc/letsencrypt/options-ssl-apache.conf
89 110
90 # Self-signed SSL cert configuration 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:
91 #SSLEngine on
92 #SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
93 #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
94 112
95 # Optional, log PHP errors, useful for debugging 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)
96 #php_flag log_errors on 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)
97 #php_flag display_errors on 115- [How to Create Self-Signed SSL Certificates with OpenSSL](http://www.xenocafe.com/tutorials/linux/centos/openssl/self_signed_certificates/index.php)
98 #php_value error_reporting 2147483647 116- [How do I create my own Certificate Authority?](https://workaround.org/certificate-authority)
99 #php_value error_log /var/log/apache2/shaarli-php-error.log
100 117
101 <Directory /absolute/path/to/shaarli/> 118--------------------------------------------------------------------------------
102 #Required for .htaccess support
103 AllowOverride All
104 Order allow,deny
105 Allow from all
106 119
107 Options Indexes FollowSymLinks MultiViews #TODO is Indexes/Multiviews required? 120## Examples
108 121
109 # Optional - required for playvideos plugin 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/`:
110 #Header set Content-Security-Policy "script-src 'self' 'unsafe-inline' https://www.youtube.com https://s.ytimg.com 'unsafe-eval'"
111 </Directory>
112 123
113</VirtualHost> 124```bash
125# create the document root (replace with your own domain name)
126sudo mkdir -p /var/www/shaarli.mydomain.org/
114``` 127```
115 128
116Enable this configuration with `sudo a2ensite shaarli` 129You can install Shaarli at the root of your virtualhost, or in a subdirectory as well. See [Directory structure](Directory-structure)
117 130
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 131
120_Note: Apache module `mod_rewrite` must be enabled to use the REST API._ 132### Apache
121 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
122 138
123## Nginx 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```
124 142
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. 143```apache
144<VirtualHost *:80>
145 ServerName shaarli.mydomain.org
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>
126 155
127<!--- TODO refactor everything below this point ---> 156# SSL/TLS configuration for Let's Encrypt certificates managed with mod_md
157#MDomain shaarli.mydomain.org
158#MDCertificateAgreement accepted
159#MDContactEmail admin@shaarli.mydomain.org
160#MDPrivateKeys RSA 4096
161
162<VirtualHost *:443>
163 ServerName shaarli.mydomain.org
164 DocumentRoot /var/www/shaarli.mydomain.org/
128 165
129### Common setup 166 # SSL/TLS configuration for Let's Encrypt certificates acquired with certbot standalone
130Once Nginx and PHP-FPM are installed, we need to ensure: 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
178 #SSLEngine on
179 #SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
180 #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
131 181
132- Nginx and PHP-FPM are running using the _same user and group_ 182 # Optional, log PHP errors, useful for debugging
133- both these user and group have 183 #php_flag log_errors on
134 - `read` permissions for Shaarli resources 184 #php_flag display_errors on
135 - `execute` permissions for Shaarli directories _AND_ their parent directories 185 #php_value error_reporting 2147483647
186 #php_value error_log /var/log/apache2/shaarli-php-error.log
136 187
137On a production server: 188 <Directory /var/www/shaarli.mydomain.org/>
189 # Required for .htaccess support
190 AllowOverride All
191 Require all granted
192 </Directory>
138 193
139- `user:group` will likely be `http:http`, `www:www` or `www-data:www-data` 194 <LocationMatch "/\.">
140- files will be located under `/var/www`, `/var/http` or `/usr/share/nginx` 195 # Prevent accessing dotfiles
196 RedirectMatch 404 ".*"
197 </LocationMatch>
141 198
142On a development server: 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>
143 203
144- files may be located in a user's home directory 204 # serve the Shaarli favicon from its custom location
145- in this case, make sure both Nginx and PHP-FPM are running as the local user/group! 205 Alias favicon.ico /var/www/shaarli.mydomain.org/images/favicon.ico
146 206
147For all following configuration examples, this user/group pair will be used: 207</VirtualHost>
208```
148 209
149- `user:group = john:users`, 210```bash
211# Enable the virtualhost
212sudo a2ensite shaarli.mydomain.org
150 213
151which corresponds to the following service configuration: 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
152 217
153```ini 218# mod_rewrite must be enabled to use the REST API
154; /etc/php/php-fpm.conf 219# https://httpd.apache.org/docs/current/mod/mod_rewrite.html
155user = john 220sudo a2enmod rewrite
156group = users
157 221
158[...] 222# mod_headers must be enabled to set custom headers from the server config
159listen.owner = john 223sudo a2enmod headers
160listen.group = users
161```
162 224
163```nginx 225# mod_version must only be enabled if you use Apache 2.2 or lower
164# /etc/nginx/nginx.conf 226# https://httpd.apache.org/docs/current/mod/mod_version.html
165user john users; 227# sudo a2enmod version
166 228
167http { 229# restart the apache service
168 [...] 230sudo systemctl restart apache2
169}
170``` 231```
171 232
172### (Optional) Increase the maximum file upload size 233- [How to install the Apache web server](https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-debian-10)
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. 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)
174 240
175To increase upload size, you will need to modify both nginx and PHP configuration:
176 241
177```nginx 242### Nginx
178# /etc/nginx/nginx.conf
179 243
180http { 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`.
181 [...]
182 245
183 client_max_body_size 10m;
184 246
185 [...] 247```bash
186} 248# install nginx and php-fpm
187``` 249sudo apt update
188 250sudo apt install nginx php-fpm
189```ini
190# /etc/php/<PHP_VERSION>/fpm/php.ini
191 251
192[...] 252# Edit the virtualhost configuration file with your favorite editor
193post_max_size = 10M 253sudo nano /etc/nginx/sites-available/shaarli.mydomain.org
194[...]
195upload_max_filesize = 10M
196``` 254```
197 255
198### Minimal
199_WARNING: Use for development only!_
200
201```nginx 256```nginx
202user john users; 257server {
203worker_processes 1; 258 listen 80;
204events { 259 server_name shaarli.mydomain.org;
205 worker_connections 1024; 260
261 # redirect all plain HTTP requests to HTTPS
262 return 301 https://shaarli.mydomain.org$request_uri;
206} 263}
207 264
208http { 265server {
209 include mime.types; 266 # ipv4 listening port/protocol
210 default_type application/octet-stream; 267 listen 443 ssl http2;
211 keepalive_timeout 20; 268 # ipv6 listening port/protocol
212 269 listen [::]:443 ssl http2;
213 index index.html index.php; 270 server_name shaarli.mydomain.org;
214 271 root /var/www/shaarli.mydomain.org;
215 server { 272
216 listen 80; 273 # log file locations
217 server_name localhost; 274 # combined log format prepends the virtualhost/domain name to log entries
218 root /home/john/web; 275 access_log /var/log/nginx/access.log combined;
219 276 error_log /var/log/nginx/error.log;
220 access_log /var/log/nginx/access.log; 277
221 error_log /var/log/nginx/error.log; 278 # paths to private key and certificates for SSL/TLS
222 279 ssl_certificate /etc/ssl/shaarli.mydomain.org.crt;
223 location /shaarli/ { 280 ssl_certificate_key /etc/ssl/private/shaarli.mydomain.org.key;
224 try_files $uri /shaarli/index.php$is_args$args; 281
225 access_log /var/log/nginx/shaarli.access.log; 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
226 error_log /var/log/nginx/shaarli.error.log; 283 ssl_session_cache shared:le_nginx_SSL:10m;
227 } 284 ssl_session_timeout 1440m;
228 285 ssl_session_tickets off;
229 location ~ (index)\.php$ { 286 ssl_protocols TLSv1.2 TLSv1.3;
230 try_files $uri =404; 287 ssl_prefer_server_ciphers off;
231 fastcgi_split_path_info ^(.+\.php)(/.+)$; 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";
232 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; 289
233 fastcgi_index index.php; 290 # increase the maximum file upload size if needed: by default nginx limits file upload to 1MB (413 Entity Too Large error)
234 include fastcgi.conf; 291 client_max_body_size 100m;
235 } 292
293 # relative path to shaarli from the root of the webserver
294 location / {
295 # default index file when no file URI is requested
296 index index.php;
297 try_files $uri /index.php$is_args$args;
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/)