-# Protocol (WIP, help welcome)
+# Architecture
## Vocabulary
- - **Network:** several servers communicating each others with this software compose a network
- - **Pod:** a server of the network (inspired from Diaspora, no really signification)
- - **Friend:** a pod that communicates with yours
- - **Origin pod:** the pod on which the video was uploaded and which is seeding (throught WebSeed protocol) the video
- - **Make friend:** the action of a server which will join a network (and so become friend with all pods that compose this network)
+ - **Fediverse:** several servers following each others
+ - **Instance:** a server which runs PeerTube in the fediverse
+ - **Origin instance:** the instance on which the video was uploaded and which is seeding (WebSeed protocol) the video
+ - **Following:** the action of a PeerTube instance which will follow another instance (subscribe to its videos)
## Base
-### The first run: join a network and make friends
- * The server generates a RSA key
- * If the server administrator wants to join a network, he just has to make an http request to the API
- * The server joins a network by checking entrypoints (server urls of the targeted network) in the configuration file
- * If the config file doesn't specify other pods, the network will be composed by this only pod
- * If the config file specifies one or more pods, the server will ask them the list of the pods in the network.
- The server will add in its friends list all pods that are in > 50% of all other pods friends list + the pods that are asked for the list. For example if there are the following pods in a network with their following friends list:
-
- http://pod1.com
- - http://pod2.com
- - http://pod3.com
- - http://pod4.com
- - http://pod5.com
-
- http://pod2.com
- - http://pod3.com
- - http://pod5.com
-
- http://pod3.com
- - http://pod5.com
-
- It will add: `http://pod1.com`, `http://pod2.com` and `http://pod3.com` because it asks to them the list of their friends. Then, it will add all pods that are in >= 50% of pods friends list so: `http://pod5.com`.
- * When the friends list is added, the server will present itself to all these friends ("make friend" operation) with the following informations: its **public RSA key** and its **URL**
- * Then, the pods will slowly share their videos database
- * All the friends have the initial score of x points which represents the reliability of this friend
- * If the score reaches 0 the friend is revoked (blacklisted for the future?) and its videos are deleted
-
### Communications
- * All the communications between pods are signed, encrypted with a RSA key and a symetric encryption in a POST request (body)
- * All the requests are retried if they failed
- * The requests are made at regular intervals to all pods of the network with a limit of parallel requests: if there are 1000 pods in the networks, the server won't make more than 10 requests in parallel
- * If there are no informations to send (no video addition/removal), no requests are made
- * The requests are grouped: for example if the interval is 1 hour and a user$ upload 2 videos there will be only 1 request that contains the 2 videos informations
- * The requests in the group are ordered: if a user add a video and remove it, we need to transmit these informations to the other pods in the same order
- * The requests are grouped with a limit: if a user uploads 100 videos at a time, the information could be propagated in a few hours to do not make too big requests
- * If a grouped request fails the score is decreased by x points
- * If a grouped request is a success the score is increased by x points
+ * All the communications between the instances are signed with [Linked Data Signatures](https://w3c-dvcg.github.io/ld-signatures/) with the private key of the account that made the action
+ * We use the [ActivityPub](https://www.w3.org/TR/activitypub/) protocol (only server-server for now). Object models could be found in [shared/models/activitypub directory](https://github.com/Chocobozzz/PeerTube/tree/develop/shared/models/activitypub).
+ * All the requests are retried several times if they fail
* The maximum of points would be defined
- * A pod which receives a request checks if the signature corresponds to the pod it has in its database. Then, it decrypts the body (or ignores it if the signature is not valid) and process the requests in the same order
-
-### Actions on a pod
- * A pod is a websocket tracker which is responsible for all the video uploaded in it
- * A pod has an administrator that can add/remove users, make friends and quit friends
- * A pod has different user accounts that can upload videos
- * All pods have an index of all videos of the network (name, origin pod url, small description, uploader username, magnet Uri, thumbnail name, created date and the thumbnail file). For example, a test with 1000000 videos (3 tags each) with alphanum characters and the following lengths: name = 50, author = 50, podHost = 25, description = 250, videoExtension = 4, remoteId = 50, infoHash = 50 and tag = 10 has a PostgreSQL size of ~ 2GB with all the useful indexes. To this, we add 1 000 000 thumbnails of 5-15 KB so 15GB maximum
- table_name | row_estimate | index | toast | table
- pod | 983416 | 140 MB | 83 MB | 57 MB
- author | 1e+06 | 229 MB | 140 MB | 89 MB
- tag | 2.96758e+06 | 309 MB | 182 MB | 127 MB
- video | 1e+06 | 723 MB | 263 MB | 460 MB
- video_tag | 3e+06 | 316 MB | 212 MB | 104 MB
-
-
- * After having uploaded a video, the server seeds it (WebSeed protocol), adds the meta data in its database and makes a secure request to all of its friends
- * If a user wants to watch a video, he asks its pod the magnetUri and the frontend adds the torrent (with WebTorrent), creates the HTML5 video tag and streams the file into it
+### Instance
+ * An instance has a websocket tracker which is responsible for all the video uploaded in it
+ * An instance has an administrator that can follow other instances
+ * An instance can be configured to follow back automatically
+ * An instance can blacklist other instances (only used in "follow back" mode)
+ * An instance cannot choose which other instance follow it, but it can decide to **reject all** followers
+ * After having uploaded a video, the instance seeds it (WebSeed protocol)
+ * If a user wants to watch a video, he asks its instance the magnet URI and the frontend adds the torrent (with WebTorrent), creates the HTML5 video player and streams the file into it
* A user watching a video seeds it too (BitTorrent) so another user who is watching the same video can get the data from the origin server and the user 1 (etc)
-
-## Ideas
-
- * A video could have more information (detailed description etc) that are not sent on other pods. The user who wants to see these informations has to ask its pod:
- user asks its pod -> user pod asks origin video pod -> origin video pod responds with the informations -> user pod responds to the user (and puts in cache the informations ?). We could extend this scheme with other informations
- * Redondance: if the origin pod is down, the video is not accessible anymore (no tracker/seeds). We could imagine a redondance between pods that keep seeding the video
- * Server could transcode the video to lower qualities (cost in CPU and disk space)
- * Add subtitles to videos
- * Avoid stocking friends URL schemes (http/https)
-
-## Debate
-
- * Is an ex-friend should be blacklisted for the future?
- * Handle API breaks in a network. If a major update breaks the API: we need the entire network update to the same major version. We could specify a limit date (2, 3 weeks after the release?) after which all the updated pod would switch to the new version of the API. The non updated pod will then be ejected of the network because would not implement the new API
Not really. Reverse proxies like Nginx handle very well requests of static files. In my tests it can send chunks at 10MB/s without consuming more than 5% of CPU on a very small VPS.
-## An index of all videos of the network won't be too large for small servers?
+## An index of all videos of servers you follow won't be too large for small servers?
No, 1000000 videos will represent around 2GB on PostgreSQL. It is acceptable for a video platform.
## I want to change my host or move to HTTPS, how can I do that?
-If you already have friends you need to quit them.
-Then, update your configuration and run `NODE_ENV=production npm run update-host` to update the torrent files.
+If you already have followers, you can't.
+
+If you don't: update your configuration and run `NODE_ENV=production npm run update-host` to update the torrent files.
- [X] Frontend
- [X] Angular frontend
-- [X] Join a network
- - [X] Generate a RSA key
- - [X] Ask for the friend list of other pods and make friend with them
- - [X] Get the list of the videos owned by a pod when making friend with it
- - [X] Post the list of its own videos when making friend with another pod
-- [X] Quit a network
+- [X] Join the fediverse
+ - [X] Follow other instances
+ - [X] Unfollow an instance
+ - [X] Get for the followers/following list
- [X] Upload a video
- [X] Seed the video
- - [X] Send the meta data to all other friends
+ - [X] Send the meta data with ActivityPub to followers
- [X] Remove the video
- [X] List the videos
-- [X] Search a video name (local index)
-- [X] View the video in an HTML5 page with WebTorrent
-- [X] Manage admin account
- - [X] Connection
- - [X] Account rights (upload...)
-- [X] Make the network auto sufficient (eject bad pods etc)
-- [X] Validate the prototype (test PeerTube in a real world)
-- [ ] Manage inter pod API breaks
-- [ ] Add "DDOS" security (check if a pod don't send too many requests for example)
+- [X] View the video in an HTML5 player with WebTorrent
- [X] Admin panel
- - [X] Stats
- - [X] Friends list
- - [X] Manage users (create/remove)
- [X] OpenGraph tags
- [X] OEmbed
- [X] Update video
- [X] Transcoding to different definitions
- [X] Download file/torrent
- [X] User video bytes quota
-- [X] User channels
+- [X] User video channels
- [X] NSFW warnings/settings
- [X] Video description in markdown
- [X] User roles (administrator, moderator)
- [X] User registration
- [X] Video privacy settings (public, unlisted or private)
-- [X] Signaling a video to the admin origin pod
+- [X] Signaling a video to the admin origin PeerTube instance
- [ ] Videos comments
- [ ] User playlist
- [ ] User subscriptions (by tags, author...)
+- [ ] Add "DDOS" security
## Installation
### Development
-In this mode, the server will run requests between pods more quickly, the video durations are limited to a few seconds.
+In this mode, the server will run requests between instances more quickly, the video durations are limited to a few seconds.
To develop on the server-side (server files are automatically compiled when we modify them and the server restarts automatically too):
$ npm run clean:server:test
$ npm run play
-Then you will get access to the three nodes at `http://localhost:900{1,2,3}` with the `root` as username and `test{1,2,3}` for the password. If you call "make friends" on `http://localhost:9002`, the pod 2 and 3 will become friends. Then if you call "make friends" on `http://localhost:9001` it will become friend with the pod 2 and 3 (check the configuration files). Then the pod will communicate with each others. If you add a video on the pod 3 you'll can see it on the pod 1 and 2 :)
+Then you will get access to the three nodes at `http://localhost:900{1,2,3}` with the `root` as username and `test{1,2,3}` for the password.
### Other commands
$ npm run help
-## Dockerfile
-
-You can test it inside Docker with the [PeerTube-Docker repository](https://github.com/Chocobozzz/PeerTube-Docker). Moreover it can help you to check how to create an environment with the required dependencies for PeerTube on a GNU/Linux distribution.
-
## Contributing
See the [contributing guide](https://github.com/Chocobozzz/PeerTube/blob/master/.github/CONTRIBUTING.md).
### Backend
* The backend is a REST API
- * Servers communicate with each others through it
- * A network is composed by servers that communicate between them
- * Each server of a network has a list of all other servers of this network
- * When a new installed server wants to join a network, it just has to get the servers list through a server that is already in the network and tell "Hi I'm new in the network, communicate with me and share me your servers list please". Then the server will "make friend" with each server of this list
- * Each server has its own users who query it (search videos, where the torrent URI of this specific video is...)
- * If a user upload a video, the server seeds it and sends the video information (name, short description, torrent URI...) to each server of the network
- * Each server has a RSA key to encrypt and sign communications with other servers
+ * Servers communicate with each others with [Activity Pub](https://www.w3.org/TR/activitypub/)
+ * Each server has its own users who query it (search videos, where the torrent URI of this specific video is...)
+ * If a user upload a video, the server seeds it and sends the video information (name, short description, torrent URI...) its followers
* A server is a tracker responsible for all the videos uploaded in it
* Even if nobody watches a video, it is seeded by the server (through [WebSeed protocol](http://www.bittorrent.org/beps/bep_0019.html)) where the video was uploaded
- * A network can live and evolve by expelling bad pod (with too many downtime for example)
-
-See the ARCHITECTURE.md for more information. Do not hesitate to give your opinion :)
Here are some simple schemes:
<img src="https://lutim.cpy.re/pqKm3Q5S.png" alt="Watch a P2P video" />
-<img src="https://lutim.cpy.re/wWVuczBz.png" alt="Join a network" />
-
-<img src="https://lutim.cpy.re/AMo3uP0D.png" alt="Many networks" />
-
</p>
-
-### Frontend
-
-There already is a frontend (Angular) but the backend is a REST API so anybody can build a frontend (Web application, desktop application...).
-The backend uses BitTorrent protocol, so users could use their favorite BitTorrent client to download/play the video with its torrent URI.
|__ initializers -> functions used at the server startup (installer, database, constants...)
|__ lib -> library function (WebTorrent, OAuth2, friends logic...)
|__ middlewares -> middlewares for controllers (requests validators, requests pagination...)
- |__ models -> Sequelize models for each SQL tables (videos, users, pods...)
+ |__ models -> Sequelize models for each SQL tables (videos, users, accounts...)
|__ tests -> API tests and real world simulations (to test the decentralized feature...)
* Run PostgreSQL and create the database `peertube_dev`.
* Run `npm run dev:server` to run the server, watch server files modifications and restart it automatically. The server (API + client) listen on `localhost:9000`.
-The `NODE_ENV=test` is set to speed up communications between pods (see [constants.ts](https://github.com/Chocobozzz/PeerTube/blob/master/server/initializers/constants.ts)).
+The `NODE_ENV=test` is set to speed up communications between instances (see [constants.ts](https://github.com/Chocobozzz/PeerTube/blob/master/server/initializers/constants.ts)).
`npm run help` gives you all available commands.
-If you want to test the decentralization feature, you can easily run 3 pods by running `npm run play`. The pods password are `test1`, `test2` and `test3`.
+If you want to test the decentralization feature, you can easily run 3 instances by running `npm run play`. The instances password are `test1`, `test2` and `test3`.
## Architecture