github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/docs/archives/architecture.md (about) 1 [Table of contents](../README.md#table-of-contents) 2 3 This document was written in september 2016. 4 5 # Cozy Stack Architecture 6 7 ## What is Cozy? 8 9 Cozy is a personal platform as a service with a focus on data. Cozy can be seen 10 as 4 layers, from inside to outside: 11 12 1. A place to keep your personal data 13 2. A core API to handle the data 14 3. Your web apps, and also the mobile & desktop clients 15 4. A coherent User Experience. 16 17 It's also a set of values: Simple, Versatile, Yours. These values mean a lot for 18 Cozy in all aspects. From an architectural point of view, it declines to: 19 20 - Simple to deploy and understand, not built as a galaxy of optimized 21 microservices managed by kubernetes that only experts can debug. 22 - Versatile, can be hosted on a Raspberry Pi for geeks to massive scale on 23 multiple servers by specialized hosting. Users can install apps. 24 - Yours, you own your data and you control it. If you want to take back your 25 data to go elsewhere, you can. 26 27 ## Overview 28 29 The architecture of Cozy is composed of: 30 31 - A reverse proxy 32 - The cozy stack 33 - A CouchDB instance to persist the JSON documents 34 - A space for storing files 35 - Optionally, Redis for caching and synchronization 36 - Optionally, a metrics server. 37 38 All of this can run on a personal server, self-hosted at home, like a Raspberry 39 Pi: 40 41 ![Architecture for a self-hosted](../diagrams/self-hosted.png) 42 43 But it's also possible to deploy a cozy on a more powerful server in order to 44 host dozens of cozy instances (an association for example). It will looks like 45 this: 46 47 ![Architecture for a medium instance](../diagrams/middle-instance.png) 48 49 And even to scale to thousands of cozy instances on a server farm, with high 50 availability: 51 52 ![Architecture for a big instance](../diagrams/big-instance.png) 53 54 This elasticity comes with some constraints: 55 56 - Most applications are run in the browser, not in the server. 57 - What must run on the server is mutualized inside the cozy stack. 58 - The cozy stack is stateless. 59 - The data is stored in couchdb and a space for files. 60 - A couchdb database is specific to an instance (no mix of data from 2 users 61 in the same database). 62 63 ### Reverse proxy 64 65 The reverse proxy is here to accept HTTPS connexions and forward the request to 66 the cozy stack. It's here mainly to manage the TLS part and binding a port < 67 1024 without needing to launch the cozy stack as root. And it's better if http/2 68 is supported, as it will make the web interface to load faster. 69 70 ### The Cozy Stack 71 72 The Cozy Stack is a single executable. It can do several things but its most 73 important usage is starting an HTTP server to serve as an API for all the 74 services of Cozy, from authentication to real-time events. This API can be used 75 on several domains. Each domain is a cozy instance for a specific user 76 ("multi-tenant"). 77 78 ### Redis 79 80 Redis is optional when there is a single cozy stack running. When available, it 81 is used to synchronize the Cozy Stacks: distributed locks for special operations 82 like installing an application, queues for recurrent jobs, etc. As a bonus, it 83 can also be used to cache some frequently used documents. 84 85 ### Databases 86 87 The JSON documents that represent the users data are stored in CouchDB, but they 88 are not mixed in a single database. We don't mix data from 2 users in the same 89 database. It's easier and safer to control the access to the data by using 90 different databases per user. 91 92 But we think to go even further by splitting the data of a user in several 93 databases, one per document type. For example, we can have a database for the 94 emails of a user and one for her todo list. This can simplify the implementation 95 of permissions (this app has access to these document types) and can improve 96 performance. CouchDB queries work with views. A view is defined ahead of its 97 usage and is built by CouchDB when it is requested and is stale, i.e. there were 98 writes in the database since the last time it was updated. So, with a single 99 database per user, it's possible to experience lag when the todolist view is 100 requested after fetching a long list of emails. By splitting the databases per 101 doctypes, we gain on two fronts: 102 103 1. The views are updated less frequently, only when documents of the matching 104 doctypes are written. 105 2. Some views are no longer necessary: those to access documents of a specific 106 doctypes. 107 108 There are downsides, mostly: 109 110 1. It can be harder to manage more databases. 111 2. It's no longer possible to use a single view for documents from doctypes that 112 are no longer in the same database. 113 114 We think that we can work on that and the pros will outweigh the cons. 115 116 ### Metrics 117 118 The Cozy Stack can generate some metrics about its usage (the size of the files 119 transfered, the number of opened connexions, the number of requests to redis, 120 etc.) and export them to a metrics backend. It will help identify the 121 bottlenecks when scaling to add more users. 122 123 [The Warp 10 Platform](http://www.warp10.io/) looks like a good candidate for 124 this. 125 126 ### Glossary 127 128 #### Instance 129 130 An instance is a logical space owned by a user and identified by a domain. For 131 example, zoe.cozycloud.cc can be the cozy instance of Zoé. This instance has a 132 space for storing files and some CouchDB databases for storing the documents of 133 its owner. 134 135 #### Environment 136 137 When creating an instance, it's possible to give an environment, `dev`, `test` 138 or `prod`. The default apps won't be the same on all environments. For example, 139 in the `dev` environment, some devtools will be installed to help the front 140 developers to create their own apps. 141 142 #### Cozy Stack Build Mode 143 144 The cozy stack can run in several modes, set by a UNIX environment variable: 145 146 - `production`, the default 147 - `development`, for coding on the cozy stack. 148 149 This mode is set when compiling the cozy-stack. It is used to show more or less 150 logs, and what is acceptable to be displayed in errors. 151 152 Even if the Cozy Stack Build Mode and Environment have similar values, they are 153 not the same. The Cozy Stack Mode will be used by core developers to hack on the 154 cozy stack. The environment will be used by front developers to hack on cozy 155 apps. 156 157 ## Services 158 159 The cozy stack came with several services. They run on the server, inside the 160 golang process and have an HTTP interface. 161 162 ### Authentication `/auth` 163 164 The cozy stack can authenticate the owner of a cozy instance. This can happen in 165 the classical web style, with a form and a cookie, but also with OAuth2 for 166 remote interactions like cozy-mobile and cozy-desktop. 167 168 ### Applications `/apps` 169 170 It's possible to manage serverless applications from the cozy stack and serve 171 them via cozy stack. The stack does the routing and serve the HTML and the 172 assets for the applications. 173 174 The assets of the applications are installed in the virtual file system. On the 175 big instances, it means that even if it is the frontal 1 that installs the 176 application, frontal 2 will still be able to serve the application by getting 177 its assets from Swift. 178 179 It will be possible to install applications from several sources (git, 180 mercurial, npm or even just a tarball). Also, we want to offer two channels for 181 our official apps: one with a stable and well tested release, and one with more 182 frequent updates for our more adventurous users. 183 184 More informations [here](../apps.md). 185 186 ### Data System `/data` 187 188 CouchDB is used for persistence of JSON documents. The data service is a layer 189 on top of it for routing the requests to the corresponding CouchDB database and 190 checking the permissions. 191 192 In particular, a serverless application can declare some contexts and access 193 data in those contexts even if it's not the owner of the cozy instance that 194 access it. For example, the owner of a cozy can create a photo album with a 195 selection of photos. This album can then be associated to a context to be shared 196 with friends of the owner. These friends can access the album and see the 197 photos, but not anonymous people. 198 199 More informations [here](../data-system.md). 200 201 ### Virtual File System `/files` 202 203 It's possible to store files on the cozy, including binary ones like photos and 204 movies, thanks to the virtual file system. It's a facade, with several 205 implementations, depending on where the files are effectively stored: 206 207 - In a directory of a local file system (easier for self-hosted users) 208 - Swift from Open Stack (convenient for massive hosting) 209 - And more storage providers, like [minio](https://minio.io/), later. 210 211 The range of possible operations with this endpoint goes from simple ones, like 212 uploading a file, to more complex ones, like renaming a folder. It also ensure 213 that an instance is not exceeding its quota, and keeps a trash to recover files 214 recently deleted. 215 216 More informations [here](../files.md). 217 218 ### Sharing `/sharings` 219 220 Users will want to share things like calendars. This service is there for 221 sharing JSON documents between cozy instances, with respect to the access 222 control. 223 224 ### Jobs `/jobs` 225 226 The cozy stack has queues where job descriptions can be put. For example, a job 227 can be to fetch the latest bills from a specific provider. These queues can be 228 consumed by external workers to complete the associated jobs. 229 230 We can imagine having a media worker that extract thumbnails from photos and 231 videos. It will fetch jobs from a media queue and each job description will 232 contain the path to the photo or video from which the thumbnail will be 233 extracted. 234 235 There is also a scheduler that acts like a crontab. It can add jobs at recurrent 236 time. For example, it can add a job for fetching github commits every hour. 237 238 Later, we can dream about having more ways to create jobs (webhooks, on document 239 creation) and make them communicate. With a web interface on that, it can become 240 a simplified [_Ifttt_](https://ifttt.com/). 241 242 ### Sync `/sync` 243 244 This endpoint will be for synchronizing your contacts and calendars by using 245 standard methods like caldav and carddav. Later, we hope to support also Webdav 246 and RemoteStorage. 247 248 ### Settings `/settings` 249 250 Each cozy instance has some settings, like its domain name, its language, the 251 name of its owner, the background for the home, etc. 252 253 ### Notifications `/notifications` 254 255 The applications can put some notifications for the user. That goes from a 256 reminder for a meeting in 10 minutes to a suggestion to update your app. 257 258 ### Real-time `/realtime` 259 260 This endpoint can be used to subscribe for real-time events. An application that 261 shows items of a specific doctype can listen for this doctype to be notified of 262 all the changes for this doctype. For example, the calendar app can listen for 263 all the events and if a synchronization with the mobile adds a new event, the 264 app will be notified and can show this new event. 265 266 ### Error catcher `/errors` 267 268 Client-side applications can have some JS errors. By sending the error, with its 269 backtrace, to this endpoint, it will be kept in a logfile to help the developers 270 debug the application later. We should look at the 271 [airbrake API](https://airbrake.io/docs/api/) and probably be compatible with it 272 to avoid redeveloping JS code to send the errors. 273 274 ### Proxy `/proxy` 275 276 It can be useful for client-side apps to get data from public APIs. But, 277 sometimes, these APIs don't have CORS enabled. A proxy endpoint can be a simple 278 but effective solution for these cases. 279 280 ### Status `/status` 281 282 It's here just to say that the API is up and that it can access the CouchDB 283 databases, for debugging and monitoring purposes. 284 285 ## Workers 286 287 The workers take jobs from the queues and process them. 288 289 ### Fetch emails `/jobs/mailbox` 290 291 It fetches a mailbox to synchronize it and see if there are some new emails. 292 293 Payload: the mailbox 294 295 ### Send email `/jobs/sendmail` 296 297 It connects to the SMTP server to send an email. 298 299 Payload: mail account, recipient, body, attachments 300 301 ### Extract metadata `/jobs/metadata` 302 303 When a file is added or updated, this worker will extract its metadata (EXIF for 304 an image, id3 for a music, etc.) 305 306 Payload: the filepath 307 308 ### Konnectors `/jobs/konnector` 309 310 It synchronizes an account on a remote service (fetch bills for example). 311 312 Payload: the kind of konnector, the credentials of the account and some optional 313 parameters (like the folder where to put the files) 314 315 ### Registry `/jobs/registry` 316 317 It updates the list of available applications. 318 319 Payload: none 320 321 ### Indexer `/jobs/indexer` 322 323 When a JSON document is added, updated or deleted, this worker will update the 324 index for full text search. [Bleve](http://www.blevesearch.com/) looks like a 325 good candidate for the indexing and full text search technology. 326 327 Payload: the doctype and the document to index 328 329 ## Serverless apps 330 331 ### Home `/apps/home` 332 333 It's where you land on your cozy and launch your apps. Having widgets to display 334 informations would be nice too! 335 336 ### Store (was marketplace) `/apps/store` 337 338 You can install new apps here. 339 340 ### Settings (was My apps) `/apps/settings` 341 342 It's a list of your installed apps and devices, and you can configure some 343 settings like your email address. 344 345 ### Collect (was konnectors) `/apps/collect` 346 347 You can configure new accounts, to fetch data from them, and see the already 348 configured accounts. 349 350 ### Devtools `/apps/devtools` 351 352 Some tools for the developpers of applications only: an API console, 353 documentation, logs of the permission checks, etc. 354 355 ### Contacts `/apps/contacts` 356 357 Manage your contact books. 358 359 ### Calendar `/apps/calendar` 360 361 Manage your events and alarms. 362 363 ### Drive `/apps/drive` 364 365 A web interface to browse your files. 366 367 ### Photos `/apps/photos` 368 369 Organize your photos and share them with friends. 370 371 ### Todo list `/apps/todo` 372 373 A task manager to never forgot what you should do. 374 375 ### Onboarding `/apps/onboarding` 376 377 Start your cozy and setup your accounts. 378 379 ## Clients 380 381 ### Mobile 382 383 Cozy-mobile is an application for android and iOS for synchronizing files, 384 contacts and calendars between the phone and the cozy instance. 385 386 ### Desktop 387 388 Cozy-desktop is a client for Linux, OSX and windows that allows to sync the 389 files in a cozy instance with a laptop or desktop. 390 391 ## Guidelines 392 393 ### The Go Programming Language 394 395 Go (often referred as golang) is an open source programming language created at 396 Google in 2007. It has nice properties for our usage: 397 398 - Simplicity (the language can be learned in weeks, not years). 399 - A focus on productivity. 400 - Good performance. 401 - A good support of concurrency with channels and goroutines. 402 403 Moreover, Go is 404 [used by a lot of companies](https://github.com/golang/go/wiki/GoUsers), is in 405 [the Top 10 of the most used languages](http://spectrum.ieee.org/computing/software/the-2016-top-programming-languages) 406 and has some known open source projects: docker, kubernetes, grafana, syncthing, 407 influxdb, caddy, etc. And it works on 408 [the ARM platforms](https://github.com/golang/go/wiki/GoArm). 409 410 Go has some tools to help the developers to format its code (`go fmt`), retrieve 411 and install external packages (`go get`), display documentation (`godoc`), check 412 for potential errors with static analysis (`go vet`), etc. Most of them can be 413 used via [gometalinter](https://github.com/alecthomas/gometalinter), which is 414 nice for continuous integration. 415 416 So, we think that writing the Cozy Stack in Go is the right choice. 417 418 ### Repository organisation 419 420 ``` 421 ├── assets The assets for the front-end 422 │ ├── images The images 423 │ ├── scripts The javascript files 424 │ ├── styles The CSS files 425 │ └── templates The HTML templates 426 ├── cmd One .go file for each command of the cozy executable 427 ├── docs Documentation, including this file 428 ├── pkg One sub-directory for each golang package 429 ├── scripts Some shell scripts for developers and testing 430 └── web One sub-directory for each of the services listed above 431 ``` 432 433 ### Rest API 434 435 We follow the best practices about Rest API (using the right status codes, HTTP 436 verbs, organise code by resources, use content-negociation, etc.). When known 437 standards make sense (caldav & carddav for example), use them. Else, 438 [JSON API](http://jsonapi.org) is a good default. 439 440 The golang web framework used for the cozy stack is 441 [Echo](https://github.com/labstack/echo/). 442 443 #### HTTP status codes 444 445 There are some HTTP status codes that are generally used in the API: 446 447 - 200 OK, when everything is OK 448 - 201 Created, when a resource was created 449 - 204 No Content, when a resource was deleted 450 - 400 Bad Request, when the request has some unknown parameters and the 451 request body is not in the expected format 452 - 401 Unauthorized, when the user is not authenticated 453 - 403 Forbidden, when the permissions forbid this action 454 - 404 Not Found, when the resouce can't be found 455 - 500 Internal Server Error, when a bug occurs 456 - 503 Service Unavailable, when the stack, CouchDB, Redis or Swift is 457 unavailable. 458 459 ### DocTypes 460 461 Each JSON document saved in CouchDB has a field `docType` that identify the kind 462 of thing it is. For example, a contact will have the docType `io.cozy.contacts`, 463 and in the cozy-doctypes repository, there will be a contacts JSON file inside 464 it that describes this doctype: 465 466 - What are the mandatory and optional fields? 467 - What is the type (string, integer, date) of the fields? 468 - Is there a validation rule for a field? 469 - How the fields can be indexed for full text search? 470 - What is the role of each field (documentation)? 471 472 This description can be used by any cozy client library (JS, Golang, etc.) to 473 generate some models to simplify the use of documents of this doctype. 474 475 When a docType has a lot of logic (calendar events for example), a JS class 476 should be shared between the several client-side apps that use this docType, in 477 order to avoid recoding this logic in each application. 478 479 ### Import and export 480 481 > You will stay because you can leave. 482 483 An important promise of Cozy is to give back to the users the control of their 484 data. And this promise is not complete with a way to export the data to use it 485 somewhere else. 486 487 The Cozy Stack will offer an export button that gives a tarball to the user with 488 the full data. She can then import it on another instance for example. It should 489 also be possible to use the data outside of Cozy. So, the format for the tarball 490 should be as simple as possible and be documented. Of course, when it's 491 possible, we will use open formats. 492 493 ### How to contribute? 494 495 Cozy's DNA is fundamentally Open Source and we want our community to thrive. 496 Having contributions (code, design, translations) is important for us and we 497 will try to create the favorable conditions to support it. 498 499 #### Adding a new konnector 500 501 Adding a konnector is easy for someone who knows JavaScript. The repository has 502 already a lot of pull requests by external contributors. The wiki has 503 documentation to explain the first steps of creating a new konnector. 3 active 504 contributors have been promoted to the maintainers team and can merge the pull 505 requests. We have done workshops to help new developers code their first 506 konnector and we will keep doing it. 507 508 #### Creating a new application 509 510 One of the goals of the new architecture is to make it easier for developers to 511 write new apps. It means having a good documentation, but also some devtools to 512 help: 513 514 - The `cozy` executable will have a command to setup a new project. 515 - The devtools on the cozy interface will give documentation about the 516 doctypes, help explore the Rest API, and check if the permissions are OK. 517 - `cozy-ui` will make it easy to reuse some widgets and offer an application 518 with a style coherent to the cozy identity. 519 - Some docTypes with heavy logic will be available as JS classes to be reused 520 in the apps. 521 522 #### Reporting a bug or suggesting a new feature 523 524 We are listening to our users. The forum is here to discuss on many subjects, 525 including how the applications are used. The issues on github are a good place 526 for bug tracking. 527 528 #### Translating to a new language 529 530 We will keep having internationalization for our applications and the 531 translations are maintained on transifex by the community. Translating to a new 532 language, or reviewing an existing one, is really appreciated. 533 534 ## FAQ 535 536 > Does the current konnectors in nodejs will be lost? 537 538 No, they won't. The business logic to scrap data from the many sources will be 539 kept and they will be adapted to fit in this new architecture. It is explained 540 how we will do that [here](../konnectors.md). 541 542 > So, it's not possible to have a custom application with a server part, like 543 > the lounge IRC client? 544 545 We want to support this use case, just not on the short term. It's not clear how 546 we can do that (while not weakening the security). One idea is to run the 547 applications in a different server, or maybe in docker. 548 549 > How to install and update cozy? 550 551 The Cozy Stack will have no auto-update mechanism. For installing and updating 552 it, you can use the classical ways: 553 554 - Using a package manager, like apt for debian & ubuntu. 555 - Using an official image for Raspberry Pi (and other embedded platforms). 556 - Using the image and services of an hosting company. 557 - Or compiling and installing it manually if you are really brave ;-) 558 559 > How to add a cozy instance to a farm? 560 561 1. Choose a (sub-)domain and configure the DNS for this (sub-)domain. 562 2. Configure the reverse-proxy to accept this (sub-)domain. 563 3. Use the `cozy` executable to configure the cozy stack. 564 565 > How to migrate from the nodejs cozy to this new architecture for cozy? 566 567 1. Export the data from the nodejs cozy (we need to add a button in the web 568 interface for that in the coming months). 569 2. Install the new cozy. 570 3. Import the data. 571 572 Please note that we don't support a continuous replication method that will 573 enable to use both the nodejs and the new architecture at the same time. It 574 looks too complicated for a temporary thing. 575 576 > How to backup the data? 577 578 There are 2 sensitive places with data: 579 580 - In CouchDB. 581 - on the place used for the Virtual File System (a directory on the local 582 filesystem, or in Swift). 583 584 You can use the tools of your choice to backup these 2 locations. The good old 585 rsync works fine (CouchDB files are append-only, except when compaction happens, 586 so it's friendly to rsync). 587 588 It's highly recommended to have an automated backup, but sometimes it can be 589 useful to have a way to backup manually the data. The "export data" button in 590 the web interface give a tarball that can be used to transfer your data from one 591 instance to another, and so, it can be used as a backup. 592 593 > Aren't microservices better for scaling? 594 595 Yes, it's often easier to scale by separating concerns, and microservices is a 596 way to achieve that. But, it has some serious downsides: 597 598 - It takes more memory and it's probably a no-go for Raspberry Pi. 599 - It's more complicated for a developper to install the whole stack before 600 coding its application. 601 - It's harder to deploy in production. 602 603 For the scalability, we can also deploy some specialized instances of the Cozy 604 Stack. For example, we can have some Cozy Stack processes dedicated for 605 real-time. Even, if they have all the code, we can route only the relevant 606 trafic from the load-balancer. 607 608 > What are the frameworks and tools used for the front-end apps? 609 610 If you want to develop your own app, you can use the framework and the tools you 611 like, nothing is mandatory. For the official apps, we will want to move to: 612 613 - es2017 (but converting the existing coffeescript code will take time) 614 - npm scripts and webpack 615 - preact & JSX. 616 617 More about this 618 [here](https://forum.cozy.io/t/a-propos-de-la-pile-technique-front-about-our-frontend-stack/3849/1) 619 620 > When will this new architecture be available? 621 622 The roadmap for Cozy v3 has been explained on our blog: 623 https://blog.cozycloud.cc/post/2016/11/21/On-the-road-to-Cozy-version-3