aboutsummaryrefslogtreecommitdiffhomepage
path: root/support
diff options
context:
space:
mode:
Diffstat (limited to 'support')
-rw-r--r--support/doc/api/openapi.yaml72
-rw-r--r--support/doc/dependencies.md14
-rw-r--r--support/doc/development/ci.md40
-rw-r--r--support/doc/development/lib.md17
-rw-r--r--support/doc/development/release.md1
-rw-r--r--support/doc/development/tests.md10
-rw-r--r--support/doc/plugins/guide.md136
-rw-r--r--support/doc/production.md128
-rw-r--r--support/docker/production/Dockerfile.bullseye15
9 files changed, 317 insertions, 116 deletions
diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml
index cfba7b361..5746d3a47 100644
--- a/support/doc/api/openapi.yaml
+++ b/support/doc/api/openapi.yaml
@@ -1,7 +1,7 @@
1openapi: 3.0.0 1openapi: 3.0.0
2info: 2info:
3 title: PeerTube 3 title: PeerTube
4 version: 3.3.0 4 version: 4.0.0
5 contact: 5 contact:
6 name: PeerTube Community 6 name: PeerTube Community
7 url: https://joinpeertube.org 7 url: https://joinpeertube.org
@@ -3792,6 +3792,39 @@ paths:
3792 '500': 3792 '500':
3793 description: search index unavailable 3793 description: search index unavailable
3794 3794
3795 /blocklist/status:
3796 get:
3797 tags:
3798 - Account Blocks
3799 - Server Blocks
3800 summary: Get block status of accounts/hosts
3801 parameters:
3802 -
3803 name: 'accounts'
3804 in: query
3805 description: 'Check if these accounts are blocked'
3806 example: [ 'goofy@example.com', 'donald@example.com' ]
3807 schema:
3808 type: array
3809 items:
3810 type: string
3811 -
3812 name: 'hosts'
3813 in: query
3814 description: 'Check if these hosts are blocked'
3815 example: [ 'example.com' ]
3816 schema:
3817 type: array
3818 items:
3819 type: string
3820 responses:
3821 '200':
3822 description: successful operation
3823 content:
3824 'application/json':
3825 schema:
3826 $ref: '#/components/schemas/BlockStatus'
3827
3795 /server/blocklist/accounts: 3828 /server/blocklist/accounts:
3796 get: 3829 get:
3797 tags: 3830 tags:
@@ -5134,6 +5167,29 @@ components:
5134 label: 5167 label:
5135 type: string 5168 type: string
5136 5169
5170 BlockStatus:
5171 properties:
5172 accounts:
5173 type: object
5174 additionalProperties:
5175 x-additionalPropertiesName: account
5176 type: object
5177 properties:
5178 blockedByServer:
5179 type: boolean
5180 blockedByUser:
5181 type: boolean
5182 hosts:
5183 type: object
5184 additionalProperties:
5185 x-additionalPropertiesName: host
5186 type: object
5187 properties:
5188 blockedByServer:
5189 type: boolean
5190 blockedByUser:
5191 type: boolean
5192
5137 NSFWPolicy: 5193 NSFWPolicy:
5138 type: string 5194 type: string
5139 enum: 5195 enum:
@@ -6623,7 +6679,7 @@ components:
6623 type: integer 6679 type: integer
6624 description: The user daily video quota in bytes 6680 description: The user daily video quota in bytes
6625 example: -1 6681 example: -1
6626 webtorrentEnabled: 6682 p2pEnabled:
6627 type: boolean 6683 type: boolean
6628 description: Enable P2P in the player 6684 description: Enable P2P in the player
6629 UserWithStats: 6685 UserWithStats:
@@ -6701,6 +6757,8 @@ components:
6701 $ref: '#/components/schemas/UserRole' 6757 $ref: '#/components/schemas/UserRole'
6702 adminFlags: 6758 adminFlags:
6703 $ref: '#/components/schemas/UserAdminFlags' 6759 $ref: '#/components/schemas/UserAdminFlags'
6760 password:
6761 $ref: '#/components/schemas/password'
6704 UpdateMe: 6762 UpdateMe:
6705 # see shared/models/users/user-update-me.model.ts: 6763 # see shared/models/users/user-update-me.model.ts:
6706 properties: 6764 properties:
@@ -6724,7 +6782,7 @@ components:
6724 - 'true' 6782 - 'true'
6725 - 'false' 6783 - 'false'
6726 - both 6784 - both
6727 webTorrentEnabled: 6785 p2pEnabled:
6728 type: boolean 6786 type: boolean
6729 description: whether to enable P2P in the player or not 6787 description: whether to enable P2P in the player or not
6730 autoPlayVideo: 6788 autoPlayVideo:
@@ -7172,6 +7230,14 @@ components:
7172 - `13` NEW_INSTANCE_FOLLOWER 7230 - `13` NEW_INSTANCE_FOLLOWER
7173 7231
7174 - `14` AUTO_INSTANCE_FOLLOWING 7232 - `14` AUTO_INSTANCE_FOLLOWING
7233
7234 - `15` ABUSE_STATE_CHANGE
7235
7236 - `16` ABUSE_NEW_MESSAGE
7237
7238 - `17` NEW_PLUGIN_VERSION
7239
7240 - `18` NEW_PEERTUBE_VERSION
7175 read: 7241 read:
7176 type: boolean 7242 type: boolean
7177 video: 7243 video:
diff --git a/support/doc/dependencies.md b/support/doc/dependencies.md
index 711fd2d7f..61b0fc6bc 100644
--- a/support/doc/dependencies.md
+++ b/support/doc/dependencies.md
@@ -77,7 +77,7 @@ sudo systemctl start redis postgresql
771. Run: 771. Run:
78 78
79``` 79```
80sudo pacman -S nodejs-lts-fermium yarn ffmpeg postgresql openssl redis git wget unzip python base-devel npm nginx 80sudo pacman -S nodejs-lts-fermium yarn ffmpeg postgresql openssl redis git wget unzip python base-devel npm nginx
81``` 81```
82 82
83Now that dependencies are installed, before running PeerTube you should start PostgreSQL and Redis: 83Now that dependencies are installed, before running PeerTube you should start PostgreSQL and Redis:
@@ -88,7 +88,7 @@ sudo systemctl start redis postgresql
88 88
89## CentOS 7 89## CentOS 7
90 90
911. Install NodeJS 12.x: 911. Install NodeJS 14.x:
92[https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora](https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora) 92[https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora](https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora)
93 93
942. Install yarn: 942. Install yarn:
@@ -135,7 +135,7 @@ sudo systemctl enable --now postgresql
135 135
136## Centos 8 136## Centos 8
137 137
1381. Install NodeJS 12.x: 1381. Install NodeJS 14.x:
139[https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora](https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora) 139[https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora](https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora)
140 140
1412. Install yarn: 1412. Install yarn:
@@ -180,9 +180,9 @@ sudo systemctl enable --now postgresql
180sudo dnf update -y 180sudo dnf update -y
181``` 181```
182 182
1832. Install NodeJS 12.x (or 14): 1832. Install NodeJS 14.x:
184``` 184```
185sudo dnf module install -y nodejs:12 185sudo dnf module install -y nodejs:14
186``` 186```
187 187
1883. Install yarn: 1883. Install yarn:
@@ -239,7 +239,7 @@ su my-peertube-user
2393. (Optional) Install certbot (choose instructions for your distribution): 2393. (Optional) Install certbot (choose instructions for your distribution):
240[https://certbot.eff.org/all-instructions](https://certbot.eff.org/all-instructions) 240[https://certbot.eff.org/all-instructions](https://certbot.eff.org/all-instructions)
241 241
2424. Install NodeJS 12.x: 2424. Install NodeJS 14.x:
243[https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora](https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora) 243[https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora](https://nodejs.org/en/download/package-manager/#enterprise-linux-and-fedora)
244 244
2455. Install yarn: 2455. Install yarn:
@@ -331,7 +331,7 @@ echo fs.inotify.max_user_watches=582222 | sudo tee -a /etc/sysctl.conf && sudo s
3312. Install Node.JS 3312. Install Node.JS
332 332
333``` 333```
334sudo dnf module install nodejs:12 334sudo dnf module install nodejs:14
335``` 335```
336 336
3373. Install Yarn 3373. Install Yarn
diff --git a/support/doc/development/ci.md b/support/doc/development/ci.md
new file mode 100644
index 000000000..7d6eef197
--- /dev/null
+++ b/support/doc/development/ci.md
@@ -0,0 +1,40 @@
1# Continuous integration
2
3PeerTube uses Github Actions as a CI platform.
4CI tasks are described in `.github/workflows`.
5
6## benchmark.yml
7
8*Scheduled*
9
10Run various benchmarks (build, API etc) and upload results on https://builds.joinpeertube.org/peertube-stats/ to be publicly consumed.
11
12## codeql.yml
13
14*Scheduled, on push on develop and on pull request*
15
16Run CodeQL task to throw code security issues in Github. https://lgtm.com/projects/g/Chocobozzz/PeerTube can also be used.
17
18## docker.yml
19
20*Scheduled and on push on master*
21
22Build `chocobozzz/peertube-webserver:latest`, `chocobozzz/peertube:production-...`, `chocobozzz/peertube:v-...` (only latest PeerTube tag) and `chocobozzz/peertube:develop-...` Docker images. Scheduled to automatically upgrade image software (Debian security issues etc).
23
24## nightly.yml
25
26*Scheduled*
27
28Build PeerTube nightly build (`develop` branch) and upload the release on https://builds.joinpeertube.org/nightly.
29
30## stats.yml
31
32*On push on develop*
33
34Create various PeerTube stats (line of codes, build size, lighthouse report) and upload results on https://builds.joinpeertube.org/peertube-stats/ to be publicly consumed.
35
36## test.yml
37
38*Scheduled, on push and pull request*
39
40Run PeerTube lint and tests.
diff --git a/support/doc/development/lib.md b/support/doc/development/lib.md
index 6b0372150..c43edbacc 100644
--- a/support/doc/development/lib.md
+++ b/support/doc/development/lib.md
@@ -2,9 +2,24 @@
2 2
3## @peertube/embed-api 3## @peertube/embed-api
4 4
5### Build 5### Build & Publish
6 6
7``` 7```
8$ cd client/src/standalone/player/ 8$ cd client/src/standalone/player/
9$ npm run build 9$ npm run build
10$ npm publish --access=public
10``` 11```
12
13## @peertube/peertube-types
14
15Typescript definition files generation is controlled by the various `tsconfig.types.json` files.
16
17The complete types package is generated via:
18
19```
20$ npm run generate-types-package 4.x.x
21$ cd packages/types/dist
22$ npm publish --access=public
23```
24
25> See [scripts/generate-types-package.ts](scripts/generate-types-package.ts) for details.
diff --git a/support/doc/development/release.md b/support/doc/development/release.md
index a9a3ca452..d62969cf2 100644
--- a/support/doc/development/release.md
+++ b/support/doc/development/release.md
@@ -15,6 +15,7 @@ NODE_APP_INSTANCE=6 NODE_ENV=test node dist/server --benchmark-startup
15 * Check CI tests are green 15 * Check CI tests are green
16 * Run BrowserStack **and** local E2E tests 16 * Run BrowserStack **and** local E2E tests
17 * Release: `GITHUB_TOKEN=my_token npm run release -- 1.x.x` 17 * Release: `GITHUB_TOKEN=my_token npm run release -- 1.x.x`
18 * Upload `tar.xz` on https://builds.joinpeertube.org/release
18 * Create a dedicated branch: `git checkout -b release/1.x.x && git push origin release/1.x.x` 19 * Create a dedicated branch: `git checkout -b release/1.x.x && git push origin release/1.x.x`
19 * Check the release is okay: https://github.com/Chocobozzz/PeerTube/releases 20 * Check the release is okay: https://github.com/Chocobozzz/PeerTube/releases
20 * Update https://peertube3.cpy.re and check it works correctly 21 * Update https://peertube3.cpy.re and check it works correctly
diff --git a/support/doc/development/tests.md b/support/doc/development/tests.md
index d0e88a5eb..02fc41147 100644
--- a/support/doc/development/tests.md
+++ b/support/doc/development/tests.md
@@ -42,7 +42,7 @@ $ npm run test # See scripts/test.sh to run a particular suite
42Most of tests can be runned using: 42Most of tests can be runned using:
43 43
44```bash 44```bash
45TS_NODE_TRANSPILE_ONLY=true mocha -- --timeout 30000 --exit -r ts-node/register -r tsconfig-paths/register --bail server/tests/api/videos/video-transcoder.ts 45TS_NODE_TRANSPILE_ONLY=true npm run mocha -- --timeout 30000 --exit -r ts-node/register -r tsconfig-paths/register --bail server/tests/api/videos/video-transcoder.ts
46``` 46```
47 47
48`server/tests/api/activitypub` tests will need different options: 48`server/tests/api/activitypub` tests will need different options:
@@ -88,13 +88,7 @@ $ BROWSERSTACK_USER=your_user BROWSERSTACK_KEY=your_key npm run e2e:browserstack
88 88
89### Add E2E tests 89### Add E2E tests
90 90
91To add E2E tests and quickly run tests using a local Chrome, first create a test instance: 91To add E2E tests and quickly run tests using a local Chrome:
92
93```bash
94$ npm run clean:server:test && NODE_APP_INSTANCE=1 NODE_ENV=test npm start
95```
96
97Then, just run your suite using:
98 92
99```bash 93```bash
100$ cd client/e2e 94$ cd client/e2e
diff --git a/support/doc/plugins/guide.md b/support/doc/plugins/guide.md
index 3785246a7..52e3b6052 100644
--- a/support/doc/plugins/guide.md
+++ b/support/doc/plugins/guide.md
@@ -16,11 +16,10 @@
16 - [Add new transcoding profiles](#add-new-transcoding-profiles) 16 - [Add new transcoding profiles](#add-new-transcoding-profiles)
17 - [Server helpers](#server-helpers) 17 - [Server helpers](#server-helpers)
18 - [Client API (themes & plugins)](#client-api-themes--plugins) 18 - [Client API (themes & plugins)](#client-api-themes--plugins)
19 - [Plugin static route](#plugin-static-route) 19 - [Get plugin static and router routes](#get-plugin-static-and-router-routes)
20 - [Notifier](#notifier) 20 - [Notifier](#notifier)
21 - [Markdown Renderer](#markdown-renderer) 21 - [Markdown Renderer](#markdown-renderer)
22 - [Auth header](#auth-header) 22 - [Auth header](#auth-header)
23 - [Plugin router route](#plugin-router-route)
24 - [Custom Modal](#custom-modal) 23 - [Custom Modal](#custom-modal)
25 - [Translate](#translate) 24 - [Translate](#translate)
26 - [Get public settings](#get-public-settings) 25 - [Get public settings](#get-public-settings)
@@ -30,6 +29,7 @@
30 - [Plugin selector on HTML elements](#plugin-selector-on-html-elements) 29 - [Plugin selector on HTML elements](#plugin-selector-on-html-elements)
31 - [HTML placeholder elements](#html-placeholder-elements) 30 - [HTML placeholder elements](#html-placeholder-elements)
32 - [Add/remove left menu links](#addremove-left-menu-links) 31 - [Add/remove left menu links](#addremove-left-menu-links)
32 - [Create client page](#create-client-page)
33 - [Publishing](#publishing) 33 - [Publishing](#publishing)
34- [Write a plugin/theme](#write-a-plugintheme) 34- [Write a plugin/theme](#write-a-plugintheme)
35 - [Clone the quickstart repository](#clone-the-quickstart-repository) 35 - [Clone the quickstart repository](#clone-the-quickstart-repository)
@@ -531,7 +531,7 @@ See the [plugin API reference](https://docs.joinpeertube.org/api-plugins) to see
531 531
532### Client API (themes & plugins) 532### Client API (themes & plugins)
533 533
534#### Plugin static route 534#### Get plugin static and router routes
535 535
536To get your plugin static route: 536To get your plugin static route:
537 537
@@ -542,6 +542,24 @@ function register (...) {
542} 542}
543``` 543```
544 544
545And to get your plugin router route, use `peertubeHelpers.getBaseRouterRoute()`:
546
547```js
548function register (...) {
549 registerHook({
550 target: 'action:video-watch.video.loaded',
551 handler: ({ video }) => {
552 fetch(peertubeHelpers.getBaseRouterRoute() + '/my/plugin/api', {
553 method: 'GET',
554 headers: peertubeHelpers.getAuthHeader()
555 }).then(res => res.json())
556 .then(data => console.log('Hi %s.', data))
557 }
558 })
559}
560```
561
562
545#### Notifier 563#### Notifier
546 564
547To notify the user with the PeerTube ToastModule: 565To notify the user with the PeerTube ToastModule:
@@ -594,27 +612,6 @@ function register (...) {
594} 612}
595``` 613```
596 614
597#### Plugin router route
598
599**PeerTube >= 3.3**
600
601To get your plugin router route, you can use `peertubeHelpers.getBaseRouterRoute()`:
602
603```js
604function register (...) {
605 registerHook({
606 target: 'action:video-watch.video.loaded',
607 handler: ({ video }) => {
608 fetch(peertubeHelpers.getBaseRouterRoute() + '/my/plugin/api', {
609 method: 'GET',
610 headers: peertubeHelpers.getAuthHeader()
611 }).then(res => res.json())
612 .then(data => console.log('Hi %s.', data))
613 }
614 })
615}
616```
617
618#### Custom Modal 615#### Custom Modal
619 616
620To show a custom modal: 617To show a custom modal:
@@ -686,18 +683,37 @@ async function register ({ registerVideoField, peertubeHelpers }) {
686 name: 'my-field-name, 683 name: 'my-field-name,
687 label: 'My added field', 684 label: 'My added field',
688 descriptionHTML: 'Optional description', 685 descriptionHTML: 'Optional description',
686
687 // type: 'input' | 'input-checkbox' | 'input-password' | 'input-textarea' | 'markdown-text' | 'markdown-enhanced' | 'select' | 'html'
688 // /!\ 'input-checkbox' could send "false" and "true" strings instead of boolean
689 type: 'input-textarea', 689 type: 'input-textarea',
690
690 default: '', 691 default: '',
692
691 // Optional, to hide a field depending on the current form state 693 // Optional, to hide a field depending on the current form state
692 // liveVideo is in the options object when the user is creating/updating a live 694 // liveVideo is in the options object when the user is creating/updating a live
693 // videoToUpdate is in the options object when the user is updating a video 695 // videoToUpdate is in the options object when the user is updating a video
694 hidden: ({ formValues, videoToUpdate, liveVideo }) => { 696 hidden: ({ formValues, videoToUpdate, liveVideo }) => {
695 return formValues.pluginData['other-field'] === 'toto' 697 return formValues.pluginData['other-field'] === 'toto'
698 },
699
700 // Optional, to display an error depending on the form state
701 error: ({ formValues, value }) => {
702 if (formValues['privacy'] !== 1 && formValues['privacy'] !== 2) return { error: false }
703 if (value === true) return { error: false }
704
705 return { error: true, text: 'Should be enabled' }
696 } 706 }
697 } 707 }
698 708
709 const videoFormOptions = {
710 // Optional, to choose to put your setting in a specific tab in video form
711 // type: 'main' | 'plugin-settings'
712 tab: 'main'
713 }
714
699 for (const type of [ 'upload', 'import-url', 'import-torrent', 'update', 'go-live' ]) { 715 for (const type of [ 'upload', 'import-url', 'import-torrent', 'update', 'go-live' ]) {
700 registerVideoField(commonOptions, { type }) 716 registerVideoField(commonOptions, { type, ...videoFormOptions })
701 } 717 }
702} 718}
703``` 719```
@@ -787,6 +803,21 @@ See the complete list on https://docs.joinpeertube.org/api-plugins
787 803
788Left menu links can be filtered (add/remove a section or add/remove links) using the `filter:left-menu.links.create.result` client hook. 804Left menu links can be filtered (add/remove a section or add/remove links) using the `filter:left-menu.links.create.result` client hook.
789 805
806#### Create client page
807
808To create a client page, register a new client route:
809
810```js
811function register ({ registerClientRoute }) {
812 registerClientRoute({
813 route: 'my-super/route',
814 onMount: ({ rootEl }) => {
815 rootEl.innerHTML = 'hello'
816 }
817 })
818}
819```
820
790 821
791### Publishing 822### Publishing
792 823
@@ -875,11 +906,62 @@ And if you don't need CSS or client script files, use an empty `array`:
875### Write code 906### Write code
876 907
877Now you can register hooks or settings, write CSS and add static directories to your plugin or your theme :) 908Now you can register hooks or settings, write CSS and add static directories to your plugin or your theme :)
909It's up to you to check the code you write will be compatible with the PeerTube NodeJS version, and will be supported by web browsers.
910
911**JavaScript**
878 912
879**Caution:** It's up to you to check the code you write will be compatible with the PeerTube NodeJS version,
880and will be supported by web browsers.
881If you want to write modern JavaScript, please use a transpiler like [Babel](https://babeljs.io/). 913If you want to write modern JavaScript, please use a transpiler like [Babel](https://babeljs.io/).
882 914
915**Typescript**
916
917If you want to use __Typescript__, you can add __PeerTube__ types as dev dependencies:
918
919```
920npm install --save-dev @peertube/peertube-types
921```
922
923This package exposes *server* definition files by default:
924```ts
925import { RegisterServerOptions } from '@peertube/peertube-types'
926
927export async function register ({ registerHook }: RegisterServerOptions) {
928 registerHook({
929 target: 'action:application.listening',
930 handler: () => displayHelloWorld()
931 })
932}
933```
934
935But it also exposes client types and various models used in __PeerTube__:
936```ts
937import { Video } from '@peertube/peertube-types';
938import { RegisterClientOptions } from '@peertube/peertube-types/client';
939
940function register({ registerHook, peertubeHelpers }: RegisterClientOptions) {
941 registerHook({
942 target: 'action:admin-plugin-settings.init',
943 handler: ({ npmName }: { npmName: string }) => {
944 if ('peertube-plugin-transcription' !== npmName) {
945 return;
946 }
947 },
948 });
949
950 registerHook({
951 target: 'action:video-watch.video.loaded',
952 handler: ({ video }: { video: Video }) => {
953 fetch(`${peertubeHelpers.getBaseRouterRoute()}/videos/${video.uuid}/captions`, {
954 method: 'PUT',
955 headers: peertubeHelpers.getAuthHeader(),
956 }).then((res) => res.json())
957 .then((data) => console.log('Hi %s.', data));
958 },
959 });
960}
961
962export { register };
963```
964
883### Add translations 965### Add translations
884 966
885If you want to translate strings of your plugin (like labels of your registered settings), create a file and add it to `package.json`: 967If you want to translate strings of your plugin (like labels of your registered settings), create a file and add it to `package.json`:
diff --git a/support/doc/production.md b/support/doc/production.md
index 790e43f31..48ecf1517 100644
--- a/support/doc/production.md
+++ b/support/doc/production.md
@@ -8,36 +8,36 @@
8Please don't install PeerTube for production on a device behind a low bandwidth connection (example: your ADSL link). 8Please don't install PeerTube for production on a device behind a low bandwidth connection (example: your ADSL link).
9If you want information about the appropriate hardware to run PeerTube, please see the [FAQ](https://joinpeertube.org/en_US/faq#should-i-have-a-big-server-to-run-peertube). 9If you want information about the appropriate hardware to run PeerTube, please see the [FAQ](https://joinpeertube.org/en_US/faq#should-i-have-a-big-server-to-run-peertube).
10 10
11### Dependencies 11### :hammer: Dependencies
12 12
13**Follow the steps of the [dependencies guide](dependencies.md).** 13Follow the steps of the [dependencies guide](dependencies.md).
14 14
15### PeerTube user 15### :construction_worker: PeerTube user
16 16
17Create a `peertube` user with `/var/www/peertube` home: 17Create a `peertube` user with `/var/www/peertube` home:
18 18
19``` 19```bash
20$ sudo useradd -m -d /var/www/peertube -s /bin/bash -p peertube peertube 20$ sudo useradd -m -d /var/www/peertube -s /bin/bash -p peertube peertube
21``` 21```
22 22
23Set its password: 23Set its password:
24``` 24```bash
25$ sudo passwd peertube 25$ sudo passwd peertube
26``` 26```
27 27
28**On FreeBSD** 28**On FreeBSD**
29 29
30``` 30```bash
31$ sudo pw useradd -n peertube -d /var/www/peertube -s /usr/local/bin/bash -m 31$ sudo pw useradd -n peertube -d /var/www/peertube -s /usr/local/bin/bash -m
32$ sudo passwd peertube 32$ sudo passwd peertube
33``` 33```
34or use `adduser` to create it interactively. 34or use `adduser` to create it interactively.
35 35
36### Database 36### :card_file_box: Database
37 37
38Create the production database and a peertube user inside PostgreSQL: 38Create the production database and a peertube user inside PostgreSQL:
39 39
40``` 40```bash
41$ cd /var/www/peertube 41$ cd /var/www/peertube
42$ sudo -u postgres createuser -P peertube 42$ sudo -u postgres createuser -P peertube
43``` 43```
@@ -45,58 +45,66 @@ $ sudo -u postgres createuser -P peertube
45Here you should enter a password for PostgreSQL `peertube` user, that should be copied in `production.yaml` file. 45Here you should enter a password for PostgreSQL `peertube` user, that should be copied in `production.yaml` file.
46Don't just hit enter else it will be empty. 46Don't just hit enter else it will be empty.
47 47
48``` 48```bash
49$ sudo -u postgres createdb -O peertube -E UTF8 -T template0 peertube_prod 49$ sudo -u postgres createdb -O peertube -E UTF8 -T template0 peertube_prod
50``` 50```
51 51
52Then enable extensions PeerTube needs: 52Then enable extensions PeerTube needs:
53 53
54``` 54```bash
55$ sudo -u postgres psql -c "CREATE EXTENSION pg_trgm;" peertube_prod 55$ sudo -u postgres psql -c "CREATE EXTENSION pg_trgm;" peertube_prod
56$ sudo -u postgres psql -c "CREATE EXTENSION unaccent;" peertube_prod 56$ sudo -u postgres psql -c "CREATE EXTENSION unaccent;" peertube_prod
57``` 57```
58 58
59### Prepare PeerTube directory 59### :page_facing_up: Prepare PeerTube directory
60 60
61Fetch the latest tagged version of Peertube 61Fetch the latest tagged version of Peertube:
62``` 62
63```bash
63$ 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" 64$ 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"
64``` 65```
65 66
66Open the peertube directory, create a few required directories 67
67``` 68Open the peertube directory, create a few required directories:
69
70```bash
68$ cd /var/www/peertube 71$ cd /var/www/peertube
69$ sudo -u peertube mkdir config storage versions 72$ sudo -u peertube mkdir config storage versions
70$ sudo -u peertube chmod 750 config/ 73$ sudo -u peertube chmod 750 config/
71``` 74```
72 75
73Download the latest version of the Peertube client, unzip it and remove the zip 76
74``` 77Download the latest version of the Peertube client, unzip it and remove the zip:
78
79```bash
75$ cd /var/www/peertube/versions 80$ cd /var/www/peertube/versions
81$ # Releases are also available on https://builds.joinpeertube.org/release
76$ sudo -u peertube wget -q "https://github.com/Chocobozzz/PeerTube/releases/download/${VERSION}/peertube-${VERSION}.zip" 82$ sudo -u peertube wget -q "https://github.com/Chocobozzz/PeerTube/releases/download/${VERSION}/peertube-${VERSION}.zip"
77$ sudo -u peertube unzip -q peertube-${VERSION}.zip && sudo -u peertube rm peertube-${VERSION}.zip 83$ sudo -u peertube unzip -q peertube-${VERSION}.zip && sudo -u peertube rm peertube-${VERSION}.zip
78``` 84```
79 85
86
80Install Peertube: 87Install Peertube:
81``` 88
89```bash
82$ cd /var/www/peertube 90$ cd /var/www/peertube
83$ sudo -u peertube ln -s versions/peertube-${VERSION} ./peertube-latest 91$ sudo -u peertube ln -s versions/peertube-${VERSION} ./peertube-latest
84$ cd ./peertube-latest && sudo -H -u peertube yarn install --production --pure-lockfile 92$ cd ./peertube-latest && sudo -H -u peertube yarn install --production --pure-lockfile
85``` 93```
86 94
87### PeerTube configuration 95### :wrench: PeerTube configuration
88 96
89Copy the default configuration file that contains the default configuration provided by PeerTube. 97Copy the default configuration file that contains the default configuration provided by PeerTube.
90You **must not** update this file. 98You **must not** update this file.
91 99
92``` 100```bash
93$ cd /var/www/peertube 101$ cd /var/www/peertube
94$ sudo -u peertube cp peertube-latest/config/default.yaml config/default.yaml 102$ sudo -u peertube cp peertube-latest/config/default.yaml config/default.yaml
95``` 103```
96 104
97Now copy the production example configuration: 105Now copy the production example configuration:
98 106
99``` 107```bash
100$ cd /var/www/peertube 108$ cd /var/www/peertube
101$ sudo -u peertube cp peertube-latest/config/production.yaml.example config/production.yaml 109$ sudo -u peertube cp peertube-latest/config/production.yaml.example config/production.yaml
102``` 110```
@@ -107,20 +115,20 @@ Keys defined in `config/production.yaml` will override keys defined in `config/d
107 115
108**PeerTube does not support webserver host change**. Even though [PeerTube CLI can help you to switch hostname](https://docs.joinpeertube.org/maintain-tools?id=update-hostjs) there's no official support for that since it is a risky operation that might result in unforeseen errors. 116**PeerTube does not support webserver host change**. Even though [PeerTube CLI can help you to switch hostname](https://docs.joinpeertube.org/maintain-tools?id=update-hostjs) there's no official support for that since it is a risky operation that might result in unforeseen errors.
109 117
110### Webserver 118### :truck: Webserver
111 119
112We only provide official configuration files for Nginx. 120We only provide official configuration files for Nginx.
113 121
114Copy the nginx configuration template: 122Copy the nginx configuration template:
115 123
116``` 124```bash
117$ sudo cp /var/www/peertube/peertube-latest/support/nginx/peertube /etc/nginx/sites-available/peertube 125$ sudo cp /var/www/peertube/peertube-latest/support/nginx/peertube /etc/nginx/sites-available/peertube
118``` 126```
119 127
120Then set the domain for the webserver configuration file. 128Then set the domain for the webserver configuration file.
121Replace `[peertube-domain]` with the domain for the peertube server. 129Replace `[peertube-domain]` with the domain for the peertube server.
122 130
123``` 131```bash
124$ sudo sed -i 's/${WEBSERVER_HOST}/[peertube-domain]/g' /etc/nginx/sites-available/peertube 132$ sudo sed -i 's/${WEBSERVER_HOST}/[peertube-domain]/g' /etc/nginx/sites-available/peertube
125$ sudo sed -i 's/${PEERTUBE_HOST}/127.0.0.1:9000/g' /etc/nginx/sites-available/peertube 133$ sudo sed -i 's/${PEERTUBE_HOST}/127.0.0.1:9000/g' /etc/nginx/sites-available/peertube
126``` 134```
@@ -128,19 +136,19 @@ $ sudo sed -i 's/${PEERTUBE_HOST}/127.0.0.1:9000/g' /etc/nginx/sites-available/p
128Then modify the webserver configuration file. Please pay attention to the `alias` keys of the static locations. 136Then modify the webserver configuration file. Please pay attention to the `alias` keys of the static locations.
129It should correspond to the paths of your storage directories (set in the configuration file inside the `storage` key). 137It should correspond to the paths of your storage directories (set in the configuration file inside the `storage` key).
130 138
131``` 139```bash
132$ sudo vim /etc/nginx/sites-available/peertube 140$ sudo vim /etc/nginx/sites-available/peertube
133``` 141```
134 142
135Activate the configuration file: 143Activate the configuration file:
136 144
137``` 145```bash
138$ sudo ln -s /etc/nginx/sites-available/peertube /etc/nginx/sites-enabled/peertube 146$ sudo ln -s /etc/nginx/sites-available/peertube /etc/nginx/sites-enabled/peertube
139``` 147```
140 148
141To generate the certificate for your domain as required to make https work you can use [Let's Encrypt](https://letsencrypt.org/): 149To generate the certificate for your domain as required to make https work you can use [Let's Encrypt](https://letsencrypt.org/):
142 150
143``` 151```bash
144$ sudo systemctl stop nginx 152$ sudo systemctl stop nginx
145$ sudo certbot certonly --standalone --post-hook "systemctl restart nginx" 153$ sudo certbot certonly --standalone --post-hook "systemctl restart nginx"
146$ sudo systemctl reload nginx 154$ sudo systemctl reload nginx
@@ -148,14 +156,14 @@ $ sudo systemctl reload nginx
148 156
149Now you have the certificates you can reload nginx: 157Now you have the certificates you can reload nginx:
150 158
151``` 159```bash
152$ sudo systemctl reload nginx 160$ sudo systemctl reload nginx
153``` 161```
154 162
155Certbot should have installed a cron to automatically renew your certificate. 163Certbot should have installed a cron to automatically renew your certificate.
156Since our nginx template supports webroot renewal, we suggest you to update the renewal config file to use the `webroot` authenticator: 164Since our nginx template supports webroot renewal, we suggest you to update the renewal config file to use the `webroot` authenticator:
157 165
158``` 166```bash
159$ # Replace authenticator = standalone by authenticator = webroot 167$ # Replace authenticator = standalone by authenticator = webroot
160$ # Add webroot_path = /var/www/certbot 168$ # Add webroot_path = /var/www/certbot
161$ sudo vim /etc/letsencrypt/renewal/your-domain.com.conf 169$ sudo vim /etc/letsencrypt/renewal/your-domain.com.conf
@@ -164,15 +172,15 @@ $ sudo vim /etc/letsencrypt/renewal/your-domain.com.conf
164**FreeBSD** 172**FreeBSD**
165On FreeBSD you can use [Dehydrated](https://dehydrated.io/) `security/dehydrated` for [Let's Encrypt](https://letsencrypt.org/) 173On FreeBSD you can use [Dehydrated](https://dehydrated.io/) `security/dehydrated` for [Let's Encrypt](https://letsencrypt.org/)
166 174
167``` 175```bash
168$ sudo pkg install dehydrated 176$ sudo pkg install dehydrated
169``` 177```
170 178
171### TCP/IP Tuning 179### :alembic: TCP/IP Tuning
172 180
173**On Linux** 181**On Linux**
174 182
175``` 183```bash
176$ sudo cp /var/www/peertube/peertube-latest/support/sysctl.d/30-peertube-tcp.conf /etc/sysctl.d/ 184$ sudo cp /var/www/peertube/peertube-latest/support/sysctl.d/30-peertube-tcp.conf /etc/sysctl.d/
177$ sudo sysctl -p /etc/sysctl.d/30-peertube-tcp.conf 185$ sudo sysctl -p /etc/sysctl.d/30-peertube-tcp.conf
178``` 186```
@@ -181,36 +189,36 @@ Your distro may enable this by default, but at least Debian 9 does not, and the
181scheduler is quite prone to "Buffer Bloat" and extreme latency when dealing with slower client 189scheduler is quite prone to "Buffer Bloat" and extreme latency when dealing with slower client
182links as we often encounter in a video server. 190links as we often encounter in a video server.
183 191
184### systemd 192### :bricks: systemd
185 193
186If your OS uses systemd, copy the configuration template: 194If your OS uses systemd, copy the configuration template:
187 195
188``` 196```bash
189$ sudo cp /var/www/peertube/peertube-latest/support/systemd/peertube.service /etc/systemd/system/ 197$ sudo cp /var/www/peertube/peertube-latest/support/systemd/peertube.service /etc/systemd/system/
190``` 198```
191 199
192Check the service file (PeerTube paths and security directives): 200Check the service file (PeerTube paths and security directives):
193 201
194``` 202```bash
195$ sudo vim /etc/systemd/system/peertube.service 203$ sudo vim /etc/systemd/system/peertube.service
196``` 204```
197 205
198 206
199Tell systemd to reload its config: 207Tell systemd to reload its config:
200 208
201``` 209```bash
202$ sudo systemctl daemon-reload 210$ sudo systemctl daemon-reload
203``` 211```
204 212
205If you want to start PeerTube on boot: 213If you want to start PeerTube on boot:
206 214
207``` 215```bash
208$ sudo systemctl enable peertube 216$ sudo systemctl enable peertube
209``` 217```
210 218
211Run: 219Run:
212 220
213``` 221```bash
214$ sudo systemctl start peertube 222$ sudo systemctl start peertube
215$ sudo journalctl -feu peertube 223$ sudo journalctl -feu peertube
216``` 224```
@@ -218,51 +226,51 @@ $ sudo journalctl -feu peertube
218**FreeBSD** 226**FreeBSD**
219On FreeBSD, copy the startup script and update rc.conf: 227On FreeBSD, copy the startup script and update rc.conf:
220 228
221``` 229```bash
222$ sudo install -m 0555 /var/www/peertube/peertube-latest/support/freebsd/peertube /usr/local/etc/rc.d/ 230$ sudo install -m 0555 /var/www/peertube/peertube-latest/support/freebsd/peertube /usr/local/etc/rc.d/
223$ sudo sysrc peertube_enable="YES" 231$ sudo sysrc peertube_enable="YES"
224``` 232```
225 233
226Run: 234Run:
227 235
228``` 236```bash
229$ sudo service peertube start 237$ sudo service peertube start
230``` 238```
231 239
232### OpenRC 240### :bricks: OpenRC
233 241
234If your OS uses OpenRC, copy the service script: 242If your OS uses OpenRC, copy the service script:
235 243
236``` 244```bash
237$ sudo cp /var/www/peertube/peertube-latest/support/init.d/peertube /etc/init.d/ 245$ sudo cp /var/www/peertube/peertube-latest/support/init.d/peertube /etc/init.d/
238``` 246```
239 247
240If you want to start PeerTube on boot: 248If you want to start PeerTube on boot:
241 249
242``` 250```bash
243$ sudo rc-update add peertube default 251$ sudo rc-update add peertube default
244``` 252```
245 253
246Run and print last logs: 254Run and print last logs:
247 255
248``` 256```bash
249$ sudo /etc/init.d/peertube start 257$ sudo /etc/init.d/peertube start
250$ tail -f /var/log/peertube/peertube.log 258$ tail -f /var/log/peertube/peertube.log
251``` 259```
252 260
253### Administrator 261### :technologist: Administrator
254 262
255The administrator password is automatically generated and can be found in the PeerTube 263The administrator password is automatically generated and can be found in the PeerTube
256logs (path defined in `production.yaml`). You can also set another password with: 264logs (path defined in `production.yaml`). You can also set another password with:
257 265
258``` 266```bash
259$ cd /var/www/peertube/peertube-latest && NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run reset-password -- -u root 267$ cd /var/www/peertube/peertube-latest && NODE_CONFIG_DIR=/var/www/peertube/config NODE_ENV=production npm run reset-password -- -u root
260``` 268```
261 269
262Alternatively you can set the environment variable `PT_INITIAL_ROOT_PASSWORD`, 270Alternatively you can set the environment variable `PT_INITIAL_ROOT_PASSWORD`,
263to your own administrator password, although it must be 6 characters or more. 271to your own administrator password, although it must be 6 characters or more.
264 272
265### What now? 273### :tada: What now?
266 274
267Now your instance is up you can: 275Now your instance is up you can:
268 276
@@ -279,7 +287,7 @@ Now your instance is up you can:
279 287
280The password it asks is PeerTube's database user password. 288The password it asks is PeerTube's database user password.
281 289
282``` 290```bash
283$ cd /var/www/peertube/peertube-latest/scripts && sudo -H -u peertube ./upgrade.sh 291$ cd /var/www/peertube/peertube-latest/scripts && sudo -H -u peertube ./upgrade.sh
284$ sudo systemctl restart peertube # Or use your OS command to restart PeerTube if you don't use systemd 292$ sudo systemctl restart peertube # Or use your OS command to restart PeerTube if you don't use systemd
285``` 293```
@@ -288,7 +296,7 @@ $ sudo systemctl restart peertube # Or use your OS command to restart PeerTube i
288 296
289Make a SQL backup 297Make a SQL backup
290 298
291``` 299```bash
292$ SQL_BACKUP_PATH="backup/sql-peertube_prod-$(date -Im).bak" && \ 300$ SQL_BACKUP_PATH="backup/sql-peertube_prod-$(date -Im).bak" && \
293 cd /var/www/peertube && sudo -u peertube mkdir -p backup && \ 301 cd /var/www/peertube && sudo -u peertube mkdir -p backup && \
294 sudo -u postgres pg_dump -F c peertube_prod | sudo -u peertube tee "$SQL_BACKUP_PATH" >/dev/null 302 sudo -u postgres pg_dump -F c peertube_prod | sudo -u peertube tee "$SQL_BACKUP_PATH" >/dev/null
@@ -296,13 +304,13 @@ $ SQL_BACKUP_PATH="backup/sql-peertube_prod-$(date -Im).bak" && \
296 304
297Fetch the latest tagged version of Peertube: 305Fetch the latest tagged version of Peertube:
298 306
299``` 307```bash
300$ 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" 308$ 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"
301``` 309```
302 310
303Download the new version and unzip it: 311Download the new version and unzip it:
304 312
305``` 313```bash
306$ cd /var/www/peertube/versions && \ 314$ cd /var/www/peertube/versions && \
307 sudo -u peertube wget -q "https://github.com/Chocobozzz/PeerTube/releases/download/${VERSION}/peertube-${VERSION}.zip" && \ 315 sudo -u peertube wget -q "https://github.com/Chocobozzz/PeerTube/releases/download/${VERSION}/peertube-${VERSION}.zip" && \
308 sudo -u peertube unzip -o peertube-${VERSION}.zip && \ 316 sudo -u peertube unzip -o peertube-${VERSION}.zip && \
@@ -311,21 +319,21 @@ $ cd /var/www/peertube/versions && \
311 319
312Install node dependencies: 320Install node dependencies:
313 321
314``` 322```bash
315$ cd /var/www/peertube/versions/peertube-${VERSION} && \ 323$ cd /var/www/peertube/versions/peertube-${VERSION} && \
316 sudo -H -u peertube yarn install --production --pure-lockfile 324 sudo -H -u peertube yarn install --production --pure-lockfile
317``` 325```
318 326
319Copy new configuration defaults values and update your configuration file: 327Copy new configuration defaults values and update your configuration file:
320 328
321``` 329```bash
322$ sudo -u peertube cp /var/www/peertube/versions/peertube-${VERSION}/config/default.yaml /var/www/peertube/config/default.yaml 330$ sudo -u peertube cp /var/www/peertube/versions/peertube-${VERSION}/config/default.yaml /var/www/peertube/config/default.yaml
323$ diff /var/www/peertube/versions/peertube-${VERSION}/config/production.yaml.example /var/www/peertube/config/production.yaml 331$ diff /var/www/peertube/versions/peertube-${VERSION}/config/production.yaml.example /var/www/peertube/config/production.yaml
324``` 332```
325 333
326Change the link to point to the latest version: 334Change the link to point to the latest version:
327 335
328``` 336```bash
329$ cd /var/www/peertube && \ 337$ cd /var/www/peertube && \
330 sudo unlink ./peertube-latest && \ 338 sudo unlink ./peertube-latest && \
331 sudo -u peertube ln -s versions/peertube-${VERSION} ./peertube-latest 339 sudo -u peertube ln -s versions/peertube-${VERSION} ./peertube-latest
@@ -335,7 +343,7 @@ $ cd /var/www/peertube && \
335 343
336Check changes in nginx configuration: 344Check changes in nginx configuration:
337 345
338``` 346```bash
339$ cd /var/www/peertube/versions 347$ cd /var/www/peertube/versions
340$ diff "$(ls --sort=t | head -2 | tail -1)/support/nginx/peertube" "$(ls --sort=t | head -1)/support/nginx/peertube" 348$ diff "$(ls --sort=t | head -2 | tail -1)/support/nginx/peertube" "$(ls --sort=t | head -1)/support/nginx/peertube"
341``` 349```
@@ -344,7 +352,7 @@ $ diff "$(ls --sort=t | head -2 | tail -1)/support/nginx/peertube" "$(ls --sort=
344 352
345Check changes in systemd configuration: 353Check changes in systemd configuration:
346 354
347``` 355```bash
348$ cd /var/www/peertube/versions 356$ cd /var/www/peertube/versions
349$ diff "$(ls --sort=t | head -2 | tail -1)/support/systemd/peertube.service" "$(ls --sort=t | head -1)/support/systemd/peertube.service" 357$ diff "$(ls --sort=t | head -2 | tail -1)/support/systemd/peertube.service" "$(ls --sort=t | head -1)/support/systemd/peertube.service"
350``` 358```
@@ -353,19 +361,19 @@ $ diff "$(ls --sort=t | head -2 | tail -1)/support/systemd/peertube.service" "$(
353 361
354If you changed your nginx configuration: 362If you changed your nginx configuration:
355 363
356``` 364```bash
357$ sudo systemctl reload nginx 365$ sudo systemctl reload nginx
358``` 366```
359 367
360If you changed your systemd configuration: 368If you changed your systemd configuration:
361 369
362``` 370```bash
363$ sudo systemctl daemon-reload 371$ sudo systemctl daemon-reload
364``` 372```
365 373
366Restart PeerTube and check the logs: 374Restart PeerTube and check the logs:
367 375
368``` 376```bash
369$ sudo systemctl restart peertube && sudo journalctl -fu peertube 377$ sudo systemctl restart peertube && sudo journalctl -fu peertube
370``` 378```
371 379
@@ -373,7 +381,7 @@ $ sudo systemctl restart peertube && sudo journalctl -fu peertube
373 381
374Change `peertube-latest` destination to the previous version and restore your SQL backup: 382Change `peertube-latest` destination to the previous version and restore your SQL backup:
375 383
376``` 384```bash
377$ OLD_VERSION="v0.42.42" && SQL_BACKUP_PATH="backup/sql-peertube_prod-2018-01-19T10:18+01:00.bak" && \ 385$ OLD_VERSION="v0.42.42" && SQL_BACKUP_PATH="backup/sql-peertube_prod-2018-01-19T10:18+01:00.bak" && \
378 cd /var/www/peertube && sudo -u peertube unlink ./peertube-latest && \ 386 cd /var/www/peertube && sudo -u peertube unlink ./peertube-latest && \
379 sudo -u peertube ln -s "versions/peertube-$OLD_VERSION" peertube-latest && \ 387 sudo -u peertube ln -s "versions/peertube-$OLD_VERSION" peertube-latest && \
diff --git a/support/docker/production/Dockerfile.bullseye b/support/docker/production/Dockerfile.bullseye
index 7b2650538..ac97ddce3 100644
--- a/support/docker/production/Dockerfile.bullseye
+++ b/support/docker/production/Dockerfile.bullseye
@@ -1,9 +1,4 @@
1FROM node:12-bullseye-slim 1FROM node:14-bullseye-slim
2
3# Allow to pass extra options to the npm run build
4# eg: --light --light-fr to not build all client languages
5# (speed up build time if i18n is not required)
6ARG NPM_RUN_BUILD_OPTS
7 2
8# Install dependencies 3# Install dependencies
9RUN apt update \ 4RUN apt update \
@@ -21,10 +16,10 @@ WORKDIR /app
21 16
22USER peertube 17USER peertube
23 18
24RUN yarn install --pure-lockfile \ 19RUN yarn install --pure-lockfile --network-timeout 1200000 --network-concurrency 20 \
25 && npm run build -- $NPM_RUN_BUILD_OPTS \ 20 && npm run build \
26 && rm -r ./node_modules ./client/node_modules \ 21 && rm -r ./node_modules ./client/node_modules ./client/.angular \
27 && yarn install --pure-lockfile --production \ 22 && yarn install --pure-lockfile --production --network-timeout 1200000 --network-concurrency 20 \
28 && yarn cache clean 23 && yarn cache clean
29 24
30USER root 25USER root