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