]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - doc/Server-configuration.md
1ab57a0a34a977f8cdeb18d7ed8882c882c4dc2b
[github/shaarli/Shaarli.git] / doc / Server-configuration.md
1 #Server configuration
2 *Example virtual host configurations for popular web servers*
3
4 - [Apache](#apache)[](.html)
5 - [Nginx](#nginx)[](.html)
6
7 ## Prerequisites
8 ### Shaarli
9 * Shaarli is installed in a directory readable/writeable by the user
10 * the correct read/write permissions have been granted to the web server _user and/or group_
11 * for HTTPS / SSL:
12 * a key pair (public, private) and a certificate have been generated
13 * the appropriate server SSL extension is installed and active
14
15 ### HTTPS, TLS and self-signed certificates
16 Related guides:
17 * [How to Create Self-Signed SSL Certificates with OpenSSL](http://www.xenocafe.com/tutorials/linux/centos/openssl/self_signed_certificates/index.php)[](.html)
18 * [How do I create my own Certificate Authority?](https://workaround.org/certificate-authority)[](.html)
19 * Generate a self-signed certificate (will trigger browser warnings) with apache2: `make-ssl-cert generate-default-snakeoil --force-overwrite` will create `/etc/ssl/certs/ssl-cert-snakeoil.pem` and `/etc/ssl/private/ssl-cert-snakeoil.key`
20
21 ### Proxies
22 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:
23 - `X-Forwarded-Proto`;
24 - `X-Forwarded-Host`;
25 - `X-Forwarded-For`.
26
27 See also [proxy-related](https://github.com/shaarli/Shaarli/issues?utf8=%E2%9C%93&q=label%3Aproxy+) issues.[](.html)
28
29 ## Apache
30 ### Minimal
31 ```apache
32 <VirtualHost *:80>
33 ServerName shaarli.my-domain.org
34 DocumentRoot /absolute/path/to/shaarli/
35 </VirtualHost>
36 ```
37 ### Debug - Log all the things!
38 This configuration will log both Apache and PHP errors, which may prove useful to identify server configuration errors.
39
40 See:
41 * [Apache/PHP - error log per VirtualHost](http://stackoverflow.com/q/176) (StackOverflow)[](.html)
42 * [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/)[](.html)
43
44 ```apache
45 <VirtualHost *:80>
46 ServerName shaarli.my-domain.org
47 DocumentRoot /absolute/path/to/shaarli/
48
49 LogLevel warn
50 ErrorLog /var/log/apache2/shaarli-error.log
51 CustomLog /var/log/apache2/shaarli-access.log combined
52
53 php_flag log_errors on
54 php_flag display_errors on
55 php_value error_reporting 2147483647
56 php_value error_log /var/log/apache2/shaarli-php-error.log
57 </VirtualHost>
58 ```
59
60 ### Standard - Keep access and error logs
61 ```apache
62 <VirtualHost *:80>
63 ServerName shaarli.my-domain.org
64 DocumentRoot /absolute/path/to/shaarli/
65
66 LogLevel warn
67 ErrorLog /var/log/apache2/shaarli-error.log
68 CustomLog /var/log/apache2/shaarli-access.log combined
69 </VirtualHost>
70 ```
71
72 ### Paranoid - Redirect HTTP (:80) to HTTPS (:443)
73 See [Server-side TLS](https://wiki.mozilla.org/Security/Server_Side_TLS#Apache) (Mozilla).[](.html)
74
75 ```apache
76 <VirtualHost *:443>
77 ServerName shaarli.my-domain.org
78 DocumentRoot /absolute/path/to/shaarli/
79
80 SSLEngine on
81 SSLCertificateFile /absolute/path/to/the/website/certificate.pem
82 SSLCertificateKeyFile /absolute/path/to/the/website/key.key
83
84 <Directory /absolute/path/to/shaarli/>
85 AllowOverride All
86 Options Indexes FollowSymLinks MultiViews
87 Order allow,deny
88 allow from all
89 </Directory>
90
91 LogLevel warn
92 ErrorLog /var/log/apache2/shaarli-error.log
93 CustomLog /var/log/apache2/shaarli-access.log combined
94 </VirtualHost>
95 <VirtualHost *:80>
96 ServerName shaarli.my-domain.org
97 Redirect 301 / https://shaarli.my-domain.org
98
99 LogLevel warn
100 ErrorLog /var/log/apache2/shaarli-error.log
101 CustomLog /var/log/apache2/shaarli-access.log combined
102 </VirtualHost>
103 ```
104
105 ## LightHttpd
106
107 ## Nginx
108 ### Foreword
109 Nginx does not natively interpret PHP scripts; to this effect, we will run a [FastCGI](https://en.wikipedia.org/wiki/FastCGI) service, to which Nginx's FastCGI module will proxy all requests to PHP resources.[](.html)
110
111 Required packages:
112 - [nginx](http://nginx.org)[](.html)
113 - [php-fpm](http://php-fpm.org) - PHP FastCGI Process Manager[](.html)
114
115 Official documentation:
116 - [Beginner's guide](http://nginx.org/en/docs/beginners_guide.html)[](.html)
117 - [ngx_http_fastcgi_module](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html)[](.html)
118 - [Pitfalls](http://wiki.nginx.org/Pitfalls)[](.html)
119
120 Community resources:
121 - [Server-side TLS (Nginx)](https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx) (Mozilla)[](.html)
122 - [PHP configuration examples](http://kbeezie.com/nginx-configuration-examples/) (Karl Blessing)[](.html)
123
124 ### Common setup
125 Once Nginx and PHP-FPM are installed, we need to ensure:
126 - Nginx and PHP-FPM are running using the _same user and group_
127 - both these user and group have
128 - `read` permissions for Shaarli resources
129 - `execute` permissions for Shaarli directories _AND_ their parent directories
130
131 On a production server:
132 - `user:group` will likely be `http:http`, `www:www` or `www-data:www-data`
133 - files will be located under `/var/www`, `/var/http` or `/usr/share/nginx`
134
135 On a development server:
136 - files may be located in a user's home directory
137 - in this case, make sure both Nginx and PHP-FPM are running as the local user/group!
138
139 For all following examples, a development configuration will be used:
140 - `user:group = john:users`,
141
142 which corresponds to the following service configuration:
143
144 ```ini
145 ; /etc/php/php-fpm.conf
146 user = john
147 group = users
148
149 [...][](.html)
150 listen.owner = john
151 listen.group = users
152 ```
153
154 ```nginx
155 # /etc/nginx/nginx.conf
156 user john users;
157
158 http {
159 [...][](.html)
160 }
161 ```
162
163 ### Minimal
164 _WARNING: Use for development only!_
165
166 ```nginx
167 user john users;
168 worker_processes 1;
169 events {
170 worker_connections 1024;
171 }
172
173 http {
174 include mime.types;
175 default_type application/octet-stream;
176 keepalive_timeout 20;
177
178 index index.html index.php;
179
180 server {
181 listen 80;
182 server_name localhost;
183 root /home/john/web;
184
185 access_log /var/log/nginx/access.log;
186 error_log /var/log/nginx/error.log;
187
188 location /shaarli/ {
189 access_log /var/log/nginx/shaarli.access.log;
190 error_log /var/log/nginx/shaarli.error.log;
191 }
192
193 location ~ (index)\.php$ {
194 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
195 fastcgi_index index.php;
196 include fastcgi.conf;
197 }
198 }
199 }
200 ```
201
202 ### Modular
203 The previous setup is sufficient for development purposes, but has several major caveats:
204 - every content that does not match the PHP rule will be sent to client browsers:
205 - dotfiles - in our case, `.htaccess`
206 - temporary files, e.g. Vim or Emacs files: `index.php~`
207 - asset / static resource caching is not optimized
208 - if serving several PHP sites, there will be a lot of duplication: `location /shaarli/`, `location /mysite/`, etc.
209
210 To solve this, we will split Nginx configuration in several parts, that will be included when needed:
211
212 ```nginx
213 # /etc/nginx/deny.conf
214 location ~ /\. {
215 # deny access to dotfiles
216 access_log off;
217 log_not_found off;
218 deny all;
219 }
220
221 location ~ ~$ {
222 # deny access to temp editor files, e.g. "script.php~"
223 access_log off;
224 log_not_found off;
225 deny all;
226 }
227 ```
228
229 ```nginx
230 # /etc/nginx/php.conf
231 location ~ (index)\.php$ {
232 # filter and proxy PHP requests to PHP-FPM
233 fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
234 fastcgi_index index.php;
235 include fastcgi.conf;
236 }
237
238 location ~ \.php$ {
239 # deny access to all other PHP scripts
240 deny all;
241 }
242 ```
243
244 ```nginx
245 # /etc/nginx/static_assets.conf
246 location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
247 expires max;
248 add_header Pragma public;
249 add_header Cache-Control "public, must-revalidate, proxy-revalidate";
250 }
251 ```
252
253 ```nginx
254 # /etc/nginx/nginx.conf
255 [...][](.html)
256
257 http {
258 [...][](.html)
259
260 root /home/john/web;
261 access_log /var/log/nginx/access.log;
262 error_log /var/log/nginx/error.log;
263
264 server {
265 # virtual host for a first domain
266 listen 80;
267 server_name my.first.domain.org;
268
269 location /shaarli/ {
270 access_log /var/log/nginx/shaarli.access.log;
271 error_log /var/log/nginx/shaarli.error.log;
272 }
273
274 include deny.conf;
275 include static_assets.conf;
276 include php.conf;
277 }
278
279 server {
280 # virtual host for a second domain
281 listen 80;
282 server_name second.domain.com;
283
284 location /minigal/ {
285 access_log /var/log/nginx/minigal.access.log;
286 error_log /var/log/nginx/minigal.error.log;
287 }
288
289 include deny.conf;
290 include static_assets.conf;
291 include php.conf;
292 }
293 }
294 ```
295
296 ### Redirect HTTP to HTTPS
297 Assuming you have generated a (self-signed) key and certificate, and they are located under `/home/john/ssl/localhost.{key,crt}`, it is pretty straightforward to set an HTTP (:80) to HTTPS (:443) redirection to force SSL/TLS usage.
298
299 ```nginx
300 # /etc/nginx/nginx.conf
301 [...][](.html)
302
303 http {
304 [...][](.html)
305
306 index index.html index.php;
307
308 root /home/john/web;
309 access_log /var/log/nginx/access.log;
310 error_log /var/log/nginx/error.log;
311
312 server {
313 listen 80;
314 server_name localhost;
315
316 return 301 https://localhost$request_uri;
317 }
318
319 server {
320 listen 443 ssl;
321 server_name localhost;
322
323 ssl_certificate /home/john/ssl/localhost.crt;
324 ssl_certificate_key /home/john/ssl/localhost.key;
325
326 location /shaarli/ {
327 access_log /var/log/nginx/shaarli.access.log;
328 error_log /var/log/nginx/shaarli.error.log;
329 }
330
331 include deny.conf;
332 include static_assets.conf;
333 include php.conf;
334 }
335 }
336 ```