Precisions and security enhancements to the production guide (#287)
[oweals/peertube.git] / support / doc / production.md
1 # Production guide
2
3   * [Installation](#installation)
4   * [Upgrade](#upgrade) 
5
6 ## Installation
7
8 **Please don't install PeerTube for production on a small device behind a low bandwidth connection because it could slow down the fediverse.**
9
10 ### Dependencies
11
12 Follow the steps of the [dependencies guide](dependencies.md).
13
14 ### PeerTube user
15
16 Create a `peertube` user with `/var/www/peertube` home:
17
18 ```
19 $ sudo useradd -m -d /var/www/peertube -s /bin/bash -p peertube peertube
20 ```
21
22 Set its password:
23 ```
24 $ sudo passwd peertube
25 ```
26
27 ### Database
28
29 Create the production database and a peertube user inside PostgreSQL:
30
31 ```
32 $ sudo -u postgres createuser -P peertube
33 $ sudo -u postgres createdb -O peertube peertube_prod
34 ```
35
36 ### Prepare PeerTube directory
37
38 Fetch the latest tagged version of Peertube
39 ```
40 $ VERSION=$(curl -s https://api.github.com/repos/chocobozzz/peertube/releases/latest | grep tag_name | cut -d '"' -f 4) && echo "Latest Peertube version is $VERSION"
41 ```
42
43 Open the peertube directory, create a few required directories
44 ```
45 $ cd /var/www/peertube && sudo -u peertube mkdir config storage versions && cd versions
46 ```
47
48 Download the latest version of the Peertube client, unzip it and remove the zip
49 ```
50 $ sudo -u peertube wget -q "https://github.com/Chocobozzz/PeerTube/releases/download/${VERSION}/peertube-${VERSION}.zip"
51 $ sudo -u peertube unzip peertube-${VERSION}.zip && sudo -u peertube rm peertube-${VERSION}.zip
52 ```
53
54 Install Peertube
55 ```
56 $ cd ../ && sudo -u peertube ln -s versions/peertube-${VERSION} ./peertube-latest
57 $ cd ./peertube-latest && sudo -H -u peertube yarn install --production --pure-lockfile
58 ```
59
60 ### PeerTube configuration
61
62 Copy example configuration:
63
64 ```
65 $ cd /var/www/peertube && sudo -u peertube cp peertube-latest/config/production.yaml.example config/production.yaml
66 ```
67
68 Then edit the `config/production.yaml` file according to your webserver
69 configuration.
70
71 ### Webserver
72
73 We only provide official configuration files for Nginx.
74
75 Copy the nginx configuration template:
76
77 ```
78 $ sudo cp /var/www/peertube/peertube-latest/support/nginx/peertube /etc/nginx/sites-available/peertube
79 ```
80
81 Then modify the webserver configuration file. Please pay attention to the `alias` keys of the static locations.
82 It should correspond to the paths of your storage directories (set in the configuration file inside the `storage` key).
83
84 ```
85 $ sudo vim /etc/nginx/sites-available/peertube
86 ```
87
88 Your Mileage May Vary, but what follows is an example of configuration for nginx with a certificate made via `certbot` ([other utilities exist](https://letsencrypt.org/docs/client-options/)):
89
90 ```
91 server {
92   listen 80;
93   listen [::]:80;
94   server_name peertube.example.com;
95
96   access_log /var/log/nginx/peertube.example.com.access.log;
97   error_log /var/log/nginx/peertube.example.com.error.log;
98
99   rewrite ^ https://$server_name$request_uri? permanent;
100 }
101
102 server {
103   listen 443 ssl http2;
104   listen [::]:443 ssl http2;
105   server_name peertube.example.com;
106
107   # For example with Let's Encrypt (you need a certificate to run https)
108   ssl_certificate      /etc/letsencrypt/live/peertube.example.com/fullchain.pem;
109   ssl_certificate_key  /etc/letsencrypt/live/peertube.example.com/privkey.pem;
110   
111   # Security hardening (as of 11/02/2018)
112   ssl_protocols TLSv1.3, TLSv1.2;# TLSv1.3 requires nginx >= 1.13.0 else use only TLSv1.2
113   ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
114   ssl_prefer_server_ciphers on;
115   ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
116   ssl_session_timeout  10m;
117   ssl_session_cache shared:SSL:10m;
118   ssl_session_tickets off; # Requires nginx >= 1.5.9
119   ssl_stapling on; # Requires nginx >= 1.3.7
120   ssl_stapling_verify on; # Requires nginx => 1.3.7
121   resolver $DNS-IP-1 $DNS-IP-2 valid=300s;
122   resolver_timeout 5s;
123   add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
124   add_header X-Frame-Options DENY;
125   add_header X-Content-Type-Options nosniff;
126   add_header X-XSS-Protection "1; mode=block";
127   add_header X-Robots-Tag none;
128   
129   access_log /var/log/nginx/peertube.example.com.access.log;
130   error_log /var/log/nginx/peertube.example.com.error.log;
131
132   location ^~ '/.well-known/acme-challenge' {
133     default_type "text/plain";
134     root /var/www/certbot;
135   }
136
137   location ~ ^/client/(.*\.(js|css|woff2|otf|ttf|woff|eot))$ {
138     add_header Cache-Control "public, max-age=31536000, immutable";
139
140     alias /var/www/peertube/peertube-latest/client/dist/$1;
141   }
142
143   location ~ ^/static/(thumbnails|avatars)/(.*)$ {
144     add_header Cache-Control "public, max-age=31536000, immutable";
145
146     alias /var/www/peertube/storage/$1/$2;
147   }
148
149   location / {
150     proxy_pass http://localhost:9000;
151     proxy_set_header X-Real-IP $remote_addr;
152     proxy_set_header Host $host;
153     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
154
155     # For the video upload
156     client_max_body_size 2G;
157     proxy_connect_timeout       600;
158     proxy_send_timeout          600;
159     proxy_read_timeout          600;
160     send_timeout                600;
161   }
162
163   # Bypass PeerTube webseed route for better performances
164   location /static/webseed {
165     # Clients usually have 4 simultaneous webseed connections, so the real limit is 3MB/s per client
166     limit_rate 800k;
167     
168     if ($request_method = 'OPTIONS') {
169       add_header 'Access-Control-Allow-Origin' '*';
170       add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
171       add_header 'Access-Control-Allow-Headers' 'Range,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
172       add_header 'Access-Control-Max-Age' 1728000;
173       add_header 'Content-Type' 'text/plain charset=UTF-8';
174       add_header 'Content-Length' 0;
175       return 204;
176     }
177
178     if ($request_method = 'GET') {
179       add_header 'Access-Control-Allow-Origin' '*';
180       add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
181       add_header 'Access-Control-Allow-Headers' 'Range,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
182
183       # Don't spam access log file with byte range requests
184       access_log off;
185     }
186
187     alias /var/www/peertube/storage/videos;
188   }
189
190   # Websocket tracker
191   location /tracker/socket {
192     # Peers send a message to the tracker every 15 minutes
193     # Don't close the websocket before this time
194     proxy_read_timeout 1200s;
195     proxy_set_header Upgrade $http_upgrade;
196     proxy_set_header Connection "upgrade";
197     proxy_http_version 1.1;
198     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
199     proxy_set_header Host $host;
200     proxy_pass http://localhost:9000;
201   }
202 }
203 ```
204
205 To generate the certificate for your domain as required to make https work, you have two alternatives (note that the second command modifies itself the Nginx configuration to point the concerned server blocks to its certificate):
206
207 ```
208 $ sudo certbot --authenticator standalone certonly -d peertube.example.com && nginx -t && systemctl reload nginx
209 ```
210
211 ```
212 $ sudo certbot --authenticator standalone --installer nginx --post-hook "nginx -t && systemctl reload nginx"
213 ```
214
215 Remember your certificate will expire in 90 days, and thus needs renewal.
216
217 Activate the configuration file:
218
219 ```
220 $ sudo ln -s /etc/nginx/sites-available/peertube /etc/nginx/sites-enabled/peertube
221 $ sudo systemctl reload nginx
222 ```
223
224 ### Systemd
225
226 Copy the SystemD configuration template:
227
228 ```
229 $ sudo cp /var/www/peertube/peertube-latest/support/systemd/peertube.service /etc/systemd/system/
230 ```
231
232 Update the service file:
233
234 ```
235 $ sudo vim /etc/systemd/system/peertube.service
236 ```
237
238 It should look like this:
239
240 ```
241 [Unit]
242 Description=PeerTube daemon
243 After=network.target
244
245 [Service]
246 Type=simple
247 Environment=NODE_ENV=production
248 Environment=NODE_CONFIG_DIR=/var/www/peertube/config
249 User=peertube
250 Group=peertube
251 ExecStart=/usr/bin/npm start
252 WorkingDirectory=/var/www/peertube/peertube-latest
253 StandardOutput=syslog
254 StandardError=syslog
255 SyslogIdentifier=peertube
256 Restart=always
257
258 [Install]
259 WantedBy=multi-user.target
260 ```
261
262
263 Tell systemd to reload its config:
264
265 ```
266 $ sudo systemctl daemon-reload
267 ```
268
269 If you want to start PeerTube on boot:
270
271 ```
272 $ sudo systemctl enable peertube
273 ```
274
275 ### Run
276
277 ```
278 $ sudo systemctl start peertube
279 $ sudo journalctl -feu peertube
280 ```
281
282 ### Administrator
283
284 The administrator password is automatically generated and can be found in the
285 logs. You can set another password with:
286
287 ```
288 $ cd /var/www/peertube/peertube-latest && NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run reset-password -- -u root
289 ```
290
291 ## Upgrade
292 #### Auto
293
294 Via the bash Script :
295
296 ```
297 $ su - peertube
298 $ cd scripts && ./upgrade.sh
299 $ exit
300 $ systemctl restart peertube
301 $ systemctl status peertube
302 ```
303
304 #### Manuel
305 Make a SQL backup
306
307 ```
308 $ SQL_BACKUP_PATH="backup/sql-peertube_prod-$(date -Im).bak" && \
309     cd /var/www/peertube && sudo -u peertube mkdir -p backup && \
310     sudo pg_dump -U peertube -W -h localhost -F c peertube_prod -f "$SQL_BACKUP_PATH"
311 ```
312
313 Fetch the latest tagged version of Peertube:
314
315 ```
316 $ VERSION=$(curl -s https://api.github.com/repos/chocobozzz/peertube/releases/latest | grep tag_name | cut -d '"' -f 4) && echo "Latest Peertube version is $VERSION"
317 ```
318
319 Download the new version and unzip it:
320
321 ```
322 $ cd /var/www/peertube/versions && \
323     sudo -u peertube wget -q "https://github.com/Chocobozzz/PeerTube/releases/download/${VERSION}/peertube-${VERSION}.zip" && \
324     sudo -u peertube unzip -o peertube-${VERSION}.zip && \
325     sudo -u peertube rm peertube-${VERSION}.zip
326 ```
327
328 Install node dependencies:
329
330 ```
331 $ cd /var/www/peertube/versions/peertube-${VERSION} && \
332     sudo -u peertube yarn install --production --pure-lockfile
333 ```
334
335 Copy new configuration defaults values and update your configuration file:
336
337 ```
338 $ sudo -u peertube cp /var/www/peertube/versions/peertube-${VERSION}/config/default.yaml /var/www/peertube/config/default.yaml
339 $ diff /var/www/peertube/versions/peertube-${VERSION}/config//production.yaml.example /var/www/peertube/config/production.yaml
340 ```
341
342 Change the link to point to the latest version:
343
344 ```
345 $ cd /var/www/peertube && \
346     sudo rm ./peertube-latest && \
347     sudo -u peertube ln -s versions/peertube-${VERSION} ./peertube-latest
348 ```
349
350
351 Restart PeerTube:
352 ```
353 $ sudo systemctl restart peertube
354 ```
355
356 ### Things went wrong? 
357
358 Change `peertube-latest` destination to the previous version and restore your SQL backup:
359
360 ```
361 $ OLD_VERSION="v0.42.42" && SQL_BACKUP_PATH="backup/sql-peertube_prod-2018-01-19T10:18+01:00.bak" && \
362     cd /var/www/peertube && rm ./peertube-latest && \
363     sudo -u peertube ln -s "versions/peertube-$OLD_VERSION" peertube-latest && \
364     pg_restore -U peertube -W -h localhost -c -d peertube_prod "$SQL_BACKUP_PATH"
365     sudo systemctl restart peertube
366 ```