Comments on How to Install CryptPad Collaborative Office Suite on Ubuntu 22.04

Cryptpad is an open-source collaborative office suite that serves as an alternative to Office 365. It allows you to access office applications via the web browser. In this tutorial, you will learn how to install the Cryptpad suite on a Ubuntu 22.04 server.

1 Comment(s)

Add comment

Please register in our forum first to comment.

Comments

By: Neil Isenor

I think I have something wrong in my cryptpad.conf file but I can't figure it out. All tests say I'm good, but when I try to access the sites, they just time out. I have ddclient working with my google domains for the hosts, and I have 80 and 443 open on my router. Also, I had to comment out line 79 and 81 because I was having errors from nginx syntax test saying they were duplicated from nginx.conf, and not sure whyt. Here's my cryptpad.conf file:server {    # Redirect any http requests to https    listen 80;    listen [::]:80;    server_name sandbox.thirsttrapravers.ca cryptpad.thirstrapravers.ca;    return 301 https://$host$request_uri;}server {    listen 443 ssl http2;    listen [::]:443 ssl http2;    # CryptPad serves static assets over these two domains.    # `main_domain` is what users will enter in their address bar.    # Privileged computation such as key management is handled in this scope    # UI content is loaded via the `sandbox_domain`.    # "Content Security Policy" headers prevent content loaded via the sandbox    # from accessing privileged information.    # These variables must be different to take advantage of CryptPad's sandboxing techniques.    # In the event of an XSS vulnerability in CryptPad's front-end code    # this will limit the amount of information accessible to attackers.    set $main_domain "sandbox.thirsttrapravers.ca";    set $sandbox_domain "cryptpad.thirsttrapravers.ca";    # By default CryptPad allows remote domains to embed CryptPad documents in iframes.    # This behaviour can be blocked by changing $allowed_origins from "*" to the    # sandbox domain, which must be permitted to load content from the main domain    # in order for CryptPad to work as expected.    #    # An example is given below which can be uncommented if you want to block    # remote sites from including content from your server    set $allowed_origins "*";    # set $allowed_origins "https://${sandbox_domain}";    # CryptPad's dynamic content (websocket traffic and encrypted blobs)    # can be served over separate domains. Using dedicated domains (or subdomains)    # for these purposes allows you to move them to a separate machine at a later date    # if you find that a single machine cannot handle all of your users.    # If you don't use dedicated domains, this can be the same as $main_domain    # If you do, they can be added as exceptions to any rules which block connections to remote domains.    # You can find these variables referenced below in the relevant places    set $api_domain "sandbox.thirsttrapravers.ca";    set $files_domain "sandbox.thirsttrapravers.ca";    # nginx doesn't let you set server_name via variables, so you need to hardcode your domains here    server_name sandbox.thirsttrapravers.ca cryptpad.thirsttrapravers.ca;    # You'll need to Set the path to your certificates and keys here    # IMPORTANT: this config is intended to serve assets for at least two domains    # (your main domain and your sandbox domain). As such, you'll need to generate a single SSL certificate    # that includes both domains in order for things to work as expected.    ssl_certificate /etc/letsencrypt/live/sandbox.thirsttrapravers.ca/fullchain.pem;    ssl_certificate_key /etc/letsencrypt/live/sandbox.thirsttrapravers.ca/privkey.pem;    ssl_trusted_certificate /etc/letsencrypt/live/sandbox.thirsttrapravers.ca/chain.pem;    # diffie-hellman parameters are used to negotiate keys for your session    # generate strong parameters using the following command    ssl_dhparam /etc/ssl/certs/dhparam.pem;    # Speeds things up a little bit when resuming a session    ssl_session_timeout 1d;    ssl_session_cache shared:MozSSL:10m;    ssl_session_tickets off;    ssl_protocols TLSv1.2 TLSv1.3;    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;    ssl_prefer_server_ciphers off;    # HSTS (ngx_http_headers_module is required) (63072000 seconds)    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;    # OCSP stapling    ssl_stapling on;    ssl_stapling_verify on;    resolver 8.8.8.8 8.8.4.4 valid=300s;    resolver_timeout 5s;    # verify chain of trust of OCSP response using Root CA and Intermediate certs    # ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;    # replace with the IP address of your resolver    # resolver 8.8.8.8 8.8.4.4 1.1.1.1 1.0.0.1 9.9.9.9 149.112.112.112 208.67.222.222 208.67.220.220;    add_header X-XSS-Protection "1; mode=block";    add_header X-Content-Type-Options nosniff;    add_header Access-Control-Allow-Origin "${allowed_origins}";    # add_header X-Frame-Options "SAMEORIGIN";    # Opt out of Google's FLoC Network    add_header Permissions-Policy interest-cohort=();    # Enable SharedArrayBuffer in Firefox (for .xlsx export)    add_header Cross-Origin-Resource-Policy cross-origin;    add_header Cross-Origin-Embedder-Policy require-corp;    # Insert the path to your CryptPad repository root here    root /home/username/cryptpad;    index index.html;    error_page 404 /customize.dist/404.html;    # any static assets loaded with "ver=" in their URL will be cached for a year    if ($args ~ ver=) {        set $cacheControl max-age=31536000;    }    # This rule overrides the above caching directive and makes things somewhat less efficient.    # We had inverted them as an optimization, but Safari 16 introduced a bug that interpreted    # some important headers incorrectly when loading these files from cache.    # This is why we can't have nice things :(    if ($uri ~ ^(\/|.*\/|.*\.html)$) {        set $cacheControl no-cache;    }    # Will not set any header if it is emptystring    add_header Cache-Control $cacheControl;    # CSS can be dynamically set inline, loaded from the same domain, or from $main_domain    set $styleSrc   "'unsafe-inline' 'self' https://${main_domain}";    # connect-src restricts URLs which can be loaded using script interfaces    # if you have configured your instance to use a dedicated $files_domain or $api_domain    # you will need to add them below as: https://${files_domain} and https://${api_domain}    set $connectSrc "'self' https://${main_domain} blob: wss://${api_domain} https://${sandbox_domain}";    # fonts can be loaded from data-URLs or the main domain    set $fontSrc    "'self' data: https://${main_domain}";    # images can be loaded from anywhere, though we'd like to deprecate this as it allows the use of images for tracking    set $imgSrc     "'self' data: blob: https://${main_domain}";    # frame-src specifies valid sources for nested browsing contexts.    # this prevents loading any iframes from anywhere other than the sandbox domain    set $frameSrc   "'self' https://${sandbox_domain} blob:";    # specifies valid sources for loading media using video or audio    set $mediaSrc   "blob:";    # defines valid sources for webworkers and nested browser contexts    # deprecated in favour of worker-src and frame-src    set $childSrc   "https://${main_domain}";    # specifies valid sources for Worker, SharedWorker, or ServiceWorker scripts.    # supercedes child-src but is unfortunately not yet universally supported.    set $workerSrc  "'self'";    # script-src specifies valid sources for javascript, including inline handlers    set $scriptSrc  "'self' resource: https://${main_domain}";    # frame-ancestors specifies which origins can embed your CryptPad instance    # this must include 'self' and your main domain (over HTTPS) in order for CryptPad to work    # if you have enabled remote embedding via the admin panel then this must be more permissive.    # note: cryptpad.fr permits web pages served via https: and vector: (element desktop app)    set $frameAncestors "'self' https://${main_domain}";    # set $frameAncestors "'self' https: vector:";    set $unsafe 0;    # the following assets are loaded via the sandbox domain    # they unfortunately still require exceptions to the sandboxing to work correctly.    if ($uri ~ ^\/(sheet|doc|presentation)\/inner.html.*$) { set $unsafe 1; }    if ($uri ~ ^\/common\/onlyoffice\/.*\/.*\.html.*$) { set $unsafe 1; }    # everything except the sandbox domain is a privileged scope, as they might be used to handle keys    if ($host != $sandbox_domain) { set $unsafe 0; }    # this iframe is an exception. Office file formats are converted outside of the sandboxed scope    # because of bugs in Chromium-based browsers that incorrectly ignore headers that are supposed to enable    # the use of some modern APIs that we require when javascript is run in a cross-origin context.    # We've applied other sandboxing techniques to mitigate the risk of running WebAssembly in this privileged scope    if ($uri ~ ^\/unsafeiframe\/inner\.html.*$) { set $unsafe 1; }    # privileged contexts allow a few more rights than unprivileged contexts, though limits are still applied    if ($unsafe) {        set $scriptSrc "'self' 'unsafe-eval' 'unsafe-inline' resource: https://${main_domain}";    }    # Finally, set all the rules you composed above.    add_header Content-Security-Policy "default-src 'none'; child-src $childSrc; worker-src $workerSrc; media-src $mediaSrc; style-src $styleSrc; script-src $scriptSrc; connect-src $connectSrc; font-src $fontSrc; img-src $imgSrc; frame-src $frameSrc; frame-ancestors $frameAncestors";    # The nodejs process can handle all traffic whether accessed over websocket or as static assets    # We prefer to serve static content from nginx directly and to leave the API server to handle    # the dynamic content that only it can manage. This is primarily an optimization    location ^~ /cryptpad_websocket {        proxy_pass http://localhost:3000;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header Host $host;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        # WebSocket support (nginx 1.4)        proxy_http_version 1.1;        proxy_set_header Upgrade $http_upgrade;        proxy_set_header Connection upgrade;    }    location ^~ /customize.dist/ {        # This is needed in order to prevent infinite recursion between /customize/ and the root    }    # try to load customizeable content via /customize/ and fall back to the default content    # located at /customize.dist/    # This is what allows you to override behaviour.    location ^~ /customize/ {        rewrite ^/customize/(.*)$ $1 break;        try_files /customize/$uri /customize.dist/$uri;    }    # /api/config is loaded once per page load and is used to retrieve    # the caching variable which is applied to every other resource    # which is loaded during that session.    location ~ ^/api/.*$ {        proxy_pass http://localhost:3000;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header Host $host;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        # These settings prevent both NGINX and the API server        # from setting the same headers and creating duplicates        proxy_hide_header Cross-Origin-Resource-Policy;        add_header Cross-Origin-Resource-Policy cross-origin;        proxy_hide_header Cross-Origin-Embedder-Policy;        add_header Cross-Origin-Embedder-Policy require-corp;    }    # encrypted blobs are immutable and are thus cached for a year    location ^~ /blob/ {        if ($request_method = 'OPTIONS') {            add_header 'Access-Control-Allow-Origin' "${allowed_origins}";            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';            add_header 'Access-Control-Max-Age' 1728000;            add_header 'Content-Type' 'application/octet-stream; charset=utf-8';            add_header 'Content-Length' 0;            return 204;        }        add_header X-Content-Type-Options nosniff;        add_header Cache-Control max-age=31536000;        add_header 'Access-Control-Allow-Origin' "${allowed_origins}";        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Content-Length';        add_header 'Access-Control-Expose-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range,Content-Length';        try_files $uri =404;    }    # the "block-store" serves encrypted payloads containing users' drive keys    # these payloads are unlocked via login credentials. They are mutable    # and are thus never cached. They're small enough that it doesn't matter, in any case.    location ^~ /block/ {        add_header X-Content-Type-Options nosniff;        add_header Cache-Control max-age=0;        try_files $uri =404;    }    # This block provides an alternative means of loading content    # otherwise only served via websocket. This is solely for debugging purposes,    # and is thus not allowed by default.    #location ^~ /datastore/ {        #add_header Cache-Control max-age=0;        #try_files $uri =404;    #}    # The nodejs server has some built-in forwarding rules to prevent    # URLs like /pad from resulting in a 404. This simply adds a trailing slash    # to a variety of applications.    location ~ ^/(register|login|settings|user|pad|drive|poll|slide|code|whiteboard|file|media|profile|contacts|todo|filepicker|debug|kanban|sheet|support|admin|notifications|teams|calendar|presentation|doc|form|report|convert|checkup)$ {        rewrite ^(.*)$ $1/ redirect;    }    # Finally, serve anything the above exceptions don't govern.    try_files /customize/www/$uri /customize/www/$uri/index.html /www/$uri /www/$uri/index.html /customize/$uri;}