tools: scripts, readme and config files
This adds a minimal setup to run the customized cryptpad instance. All info is in the readme.md. The config.js and nginx.conf will go away at some point, once a central qcode infra repo is in place.pull/1/head
parent
57e1445e3f
commit
e1224868e0
@ -0,0 +1,3 @@
|
||||
**/.git
|
||||
cryptpad/config/config.js
|
||||
cryptpad/customize
|
@ -0,0 +1 @@
|
||||
build
|
@ -0,0 +1,18 @@
|
||||
FROM node:16.14-slim AS build
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install -yq git ca-certificates && \
|
||||
npm install -g bower
|
||||
|
||||
# the bootstrap is created in tools/build-prod.sh
|
||||
COPY build/bootstrap.tar /
|
||||
RUN mkdir -p /build && \
|
||||
cd /build && \
|
||||
tar -xf /bootstrap.tar && \
|
||||
npm ci && \
|
||||
bower install --allow-root --production
|
||||
|
||||
FROM node:16.14-alpine
|
||||
COPY --from=build /build /app
|
||||
WORKDIR /app
|
@ -0,0 +1,288 @@
|
||||
/* globals module */
|
||||
|
||||
/* DISCLAIMER:
|
||||
|
||||
There are two recommended methods of running a CryptPad instance:
|
||||
|
||||
1. Using a standalone nodejs server without HTTPS (suitable for local development)
|
||||
2. Using NGINX to serve static assets and to handle HTTPS for API server's websocket traffic
|
||||
|
||||
We do not officially recommend or support Apache, Docker, Kubernetes, Traefik, or any other configuration.
|
||||
Support requests for such setups should be directed to their authors.
|
||||
|
||||
If you're having difficulty difficulty configuring your instance
|
||||
we suggest that you join the project's IRC/Matrix channel.
|
||||
|
||||
If you don't have any difficulty configuring your instance and you'd like to
|
||||
support us for the work that went into making it pain-free we are quite happy
|
||||
to accept donations via our opencollective page: https://opencollective.com/cryptpad
|
||||
|
||||
*/
|
||||
module.exports = {
|
||||
/* CryptPad is designed to serve its content over two domains.
|
||||
* Account passwords and cryptographic content is handled on the 'main' domain,
|
||||
* while the user interface is loaded on a 'sandbox' domain
|
||||
* which can only access information which the main domain willingly shares.
|
||||
*
|
||||
* In the event of an XSS vulnerability in the UI (that's bad)
|
||||
* this system prevents attackers from gaining access to your account (that's good).
|
||||
*
|
||||
* Most problems with new instances are related to this system blocking access
|
||||
* because of incorrectly configured sandboxes. If you only see a white screen
|
||||
* when you try to load CryptPad, this is probably the cause.
|
||||
*
|
||||
* PLEASE READ THE FOLLOWING COMMENTS CAREFULLY.
|
||||
*
|
||||
*/
|
||||
|
||||
/* httpUnsafeOrigin is the URL that clients will enter to load your instance.
|
||||
* Any other URL that somehow points to your instance is supposed to be blocked.
|
||||
* The default provided below assumes you are loading CryptPad from a server
|
||||
* which is running on the same machine, using port 3000.
|
||||
*
|
||||
* In a production instance this should be available ONLY over HTTPS
|
||||
* using the default port for HTTPS (443) ie. https://cryptpad.fr
|
||||
* In such a case this should be also handled by NGINX, as documented in
|
||||
* cryptpad/docs/example.nginx.conf (see the $main_domain variable)
|
||||
*
|
||||
* Note: you may provide multiple origins for the purpose of accessing
|
||||
* a development instance via different URLs, like so:
|
||||
* httpUnsafeOrigin: 'http://127.0.0.1:3000/ http://localhost:3000/',
|
||||
*
|
||||
* Such configuration is not recommended for production instances,
|
||||
* as the development team does not actively test such configuration
|
||||
* and it may have unintended consequences in practice.
|
||||
*
|
||||
*/
|
||||
httpUnsafeOrigin: 'https://cryptpad.qcode.ch',
|
||||
|
||||
/* httpSafeOrigin is the URL that is used for the 'sandbox' described above.
|
||||
* If you're testing or developing with CryptPad on your local machine then
|
||||
* it is appropriate to leave this blank. The default behaviour is to serve
|
||||
* the main domain over port 3000 and to serve the content over port 3001.
|
||||
*
|
||||
* This is not appropriate in a production environment where invasive networks
|
||||
* may filter traffic going over abnormal ports.
|
||||
* To correctly configure your production instance you must provide a URL
|
||||
* with a different domain (a subdomain is sufficient).
|
||||
* It will be used to load the UI in our 'sandbox' system.
|
||||
*
|
||||
* This value corresponds to the $sandbox_domain variable
|
||||
* in the example nginx file.
|
||||
*
|
||||
* CUSTOMIZE AND UNCOMMENT THIS FOR PRODUCTION INSTALLATIONS.
|
||||
*/
|
||||
httpSafeOrigin: 'https://cryptpad.qcodecdn.ch',
|
||||
|
||||
/* httpAddress specifies the address on which the nodejs server
|
||||
* should be accessible. By default it will listen on 127.0.0.1
|
||||
* (IPv4 localhost on most systems). If you want it to listen on
|
||||
* all addresses, including IPv6, set this to '::'.
|
||||
*
|
||||
*/
|
||||
httpAddress: '127.0.0.1',
|
||||
|
||||
/* httpPort specifies on which port the nodejs server should listen.
|
||||
* By default it will serve content over port 3000, which is suitable
|
||||
* for both local development and for use with the provided nginx example,
|
||||
* which will proxy websocket traffic to your node server.
|
||||
*
|
||||
*/
|
||||
httpPort: 3000,
|
||||
|
||||
/* httpSafePort allows you to specify an alternative port from which
|
||||
* the node process should serve sandboxed assets. The default value is
|
||||
* that of your httpPort + 1. You probably don't need to change this.
|
||||
*
|
||||
*/
|
||||
//httpSafePort: 3001,
|
||||
|
||||
/* CryptPad will launch a child process for every core available
|
||||
* in order to perform CPU-intensive tasks in parallel.
|
||||
* Some host environments may have a very large number of cores available
|
||||
* or you may want to limit how much computing power CryptPad can take.
|
||||
* If so, set 'maxWorkers' to a positive integer.
|
||||
*/
|
||||
// maxWorkers: 4,
|
||||
|
||||
/* =====================
|
||||
* Admin
|
||||
* ===================== */
|
||||
|
||||
/*
|
||||
* CryptPad contains an administration panel. Its access is restricted to specific
|
||||
* users using the following list.
|
||||
* To give access to the admin panel to a user account, just add their public signing
|
||||
* key, which can be found on the settings page for registered users.
|
||||
* Entries should be strings separated by a comma.
|
||||
*/
|
||||
adminKeys: [
|
||||
'[admin@cryptpad.qcode.ch/LSxbkUbVQbJZ8Tqna6Y2gg69iI0eRclGe+NjJrtiW-A=]',
|
||||
'[x1ddos@cryptpad.qcode.ch/w74oU0GPvPc9OxX+2l0kefvQOSZwI61E4lpZeACJlTw=]',
|
||||
],
|
||||
adminEmail: 'root@qcode.ch',
|
||||
|
||||
/* =====================
|
||||
* STORAGE
|
||||
* ===================== */
|
||||
|
||||
/* Pads that are not 'pinned' by any registered user can be set to expire
|
||||
* after a configurable number of days of inactivity (default 90 days).
|
||||
* The value can be changed or set to false to remove expiration.
|
||||
* Expired pads can then be removed using a cron job calling the
|
||||
* `evict-inactive.js` script with node
|
||||
*
|
||||
* defaults to 90 days if nothing is provided
|
||||
*/
|
||||
inactiveTime: false,
|
||||
|
||||
/* CryptPad archives some data instead of deleting it outright.
|
||||
* This archived data still takes up space and so you'll probably still want to
|
||||
* remove these files after a brief period.
|
||||
*
|
||||
* cryptpad/scripts/evict-inactive.js is intended to be run daily
|
||||
* from a crontab or similar scheduling service.
|
||||
*
|
||||
* The intent with this feature is to provide a safety net in case of accidental
|
||||
* deletion. Set this value to the number of days you'd like to retain
|
||||
* archived data before it's removed permanently.
|
||||
*
|
||||
* defaults to 15 days if nothing is provided
|
||||
*/
|
||||
archiveRetentionTime: 7,
|
||||
|
||||
/* It's possible to configure your instance to remove data
|
||||
* stored on behalf of inactive accounts. Set 'accountRetentionTime'
|
||||
* to the number of days an account can remain idle before its
|
||||
* documents and other account data is removed.
|
||||
*
|
||||
* Leave this value commented out to preserve all data stored
|
||||
* by user accounts regardless of inactivity.
|
||||
*/
|
||||
accountRetentionTime: 365,
|
||||
|
||||
/* Starting with CryptPad 3.23.0, the server automatically runs
|
||||
* the script responsible for removing inactive data according to
|
||||
* your configured definition of inactivity. Set this value to `true`
|
||||
* if you prefer not to remove inactive data, or if you prefer to
|
||||
* do so manually using `scripts/evict-inactive.js`.
|
||||
*/
|
||||
//disableIntegratedEviction: true,
|
||||
|
||||
|
||||
/* Max Upload Size (bytes)
|
||||
* this sets the maximum size of any one file uploaded to the server.
|
||||
* anything larger than this size will be rejected
|
||||
* defaults to 20MB if no value is provided
|
||||
*/
|
||||
maxUploadSize: 100 * 1024 * 1024,
|
||||
|
||||
/* Users with premium accounts (those with a plan included in their customLimit)
|
||||
* can benefit from an increased upload size limit. By default they are restricted to the same
|
||||
* upload size as any other registered user.
|
||||
*
|
||||
*/
|
||||
//premiumUploadSize: 100 * 1024 * 1024,
|
||||
|
||||
/* =====================
|
||||
* DATABASE VOLUMES
|
||||
* ===================== */
|
||||
|
||||
/*
|
||||
* CryptPad stores each document in an individual file on your hard drive.
|
||||
* Specify a directory where files should be stored.
|
||||
* It will be created automatically if it does not already exist.
|
||||
*/
|
||||
filePath: './data/datastore/',
|
||||
|
||||
/* CryptPad offers the ability to archive data for a configurable period
|
||||
* before deleting it, allowing a means of recovering data in the event
|
||||
* that it was deleted accidentally.
|
||||
*
|
||||
* To set the location of this archive directory to a custom value, change
|
||||
* the path below:
|
||||
*/
|
||||
archivePath: './data/archive',
|
||||
|
||||
/* CryptPad allows logged in users to request that particular documents be
|
||||
* stored by the server indefinitely. This is called 'pinning'.
|
||||
* Pin requests are stored in a pin-store. The location of this store is
|
||||
* defined here.
|
||||
*/
|
||||
pinPath: './data/pins',
|
||||
|
||||
/* if you would like the list of scheduled tasks to be stored in
|
||||
a custom location, change the path below:
|
||||
*/
|
||||
taskPath: './data/tasks',
|
||||
|
||||
/* if you would like users' authenticated blocks to be stored in
|
||||
a custom location, change the path below:
|
||||
*/
|
||||
blockPath: './data/block',
|
||||
|
||||
/* CryptPad allows logged in users to upload encrypted files. Files/blobs
|
||||
* are stored in a 'blob-store'. Set its location here.
|
||||
*/
|
||||
blobPath: './data/blob',
|
||||
|
||||
/* CryptPad stores incomplete blobs in a 'staging' area until they are
|
||||
* fully uploaded. Set its location here.
|
||||
*/
|
||||
blobStagingPath: './data/blobstage',
|
||||
|
||||
decreePath: './data/decrees',
|
||||
|
||||
/* CryptPad supports logging events directly to the disk in a 'logs' directory
|
||||
* Set its location here, or set it to false (or nothing) if you'd rather not log
|
||||
*/
|
||||
logPath: './data/logs',
|
||||
|
||||
/* =====================
|
||||
* Debugging
|
||||
* ===================== */
|
||||
|
||||
/* CryptPad can log activity to stdout
|
||||
* This may be useful for debugging
|
||||
*/
|
||||
logToStdout: true,
|
||||
|
||||
/* CryptPad can be configured to log more or less
|
||||
* the various settings are listed below by order of importance
|
||||
*
|
||||
* silly, verbose, debug, feedback, info, warn, error
|
||||
*
|
||||
* Choose the least important level of logging you wish to see.
|
||||
* For example, a 'silly' logLevel will display everything,
|
||||
* while 'info' will display 'info', 'warn', and 'error' logs
|
||||
*
|
||||
* This will affect both logging to the console and the disk.
|
||||
*/
|
||||
logLevel: 'debug',
|
||||
|
||||
/* clients can use the /settings/ app to opt out of usage feedback
|
||||
* which informs the server of things like how much each app is being
|
||||
* used, and whether certain clientside features are supported by
|
||||
* the client's browser. The intent is to provide feedback to the admin
|
||||
* such that the service can be improved. Enable this with `true`
|
||||
* and ignore feedback with `false` or by commenting the attribute
|
||||
*
|
||||
* You will need to set your logLevel to include 'feedback'. Set this
|
||||
* to false if you'd like to exclude feedback from your logs.
|
||||
*/
|
||||
logFeedback: false,
|
||||
|
||||
/* CryptPad supports verbose logging
|
||||
* (false by default)
|
||||
*/
|
||||
verbose: true,
|
||||
|
||||
/* Surplus information:
|
||||
*
|
||||
* 'installMethod' is included in server telemetry to voluntarily
|
||||
* indicate how many instances are using unofficial installation methods
|
||||
* such as Docker.
|
||||
*
|
||||
*/
|
||||
installMethod: 'unspecified',
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="cp" id="four-oh-four">
|
||||
<!-- If this file is not called customize.dist/src/template.html, it is generated -->
|
||||
<head>
|
||||
<title data-localization="main_title">CryptPad: Collaboration suite, encrypted and open-source</title>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<link rel="icon" type="image/png" href="/customize/favicon/main-favicon.png" id="favicon"/>
|
||||
<script async data-bootload="/customize/four-oh-four.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||
</head>
|
||||
<body class="html">
|
||||
<noscript>
|
||||
<h1>404</h1>
|
||||
<h3>We couldn't find the page you were looking for</h3>
|
||||
|
||||
</noscript>
|
@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="cp" id="five-hundred">
|
||||
<!-- If this file is not called customize.dist/src/template.html, it is generated -->
|
||||
<head>
|
||||
<title data-localization="main_title">CryptPad: Collaboration suite, encrypted and open-source</title>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<link rel="icon" type="image/png" href="/customize/favicon/main-favicon.png" id="favicon"/>
|
||||
<script async data-bootload="/customize/four-oh-four.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||
</head>
|
||||
<body class="html">
|
||||
<noscript>
|
||||
<h1>500</h1>
|
||||
<h3>Internal server error</h3>
|
||||
|
||||
</noscript>
|
@ -0,0 +1,19 @@
|
||||
// see all options in www/common/application_config_internal.js
|
||||
define(['/common/application_config_internal.js'], function (AppConfig) {
|
||||
// remove the survey link in the menu
|
||||
AppConfig.surveyURL = "";
|
||||
|
||||
// show all app types in document creation dialog
|
||||
AppConfig.hiddenTypes = [];
|
||||
|
||||
// enable OnlyOffice docs and preso support
|
||||
AppConfig.enableEarlyAccess = true;
|
||||
|
||||
// user passwords are hashed with scrypt, and salted with their username.
|
||||
// this value will be appended to the username, causing the resulting hash
|
||||
// to differ from other CryptPad instances if customized.
|
||||
AppConfig.loginSalt = '';
|
||||
AppConfig.minimumPasswordLength = 8;
|
||||
|
||||
return AppConfig;
|
||||
});
|
@ -0,0 +1,219 @@
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
|
||||
server_name cryptpad.qcode.ch cryptpad.qcodecdn.ch;
|
||||
|
||||
access_log /var/log/nginx/cryptpad.log;
|
||||
error_log /var/log/nginx/cryptpad.log;
|
||||
|
||||
# expected to cover both main and sandbox hostnames.
|
||||
ssl_certificate /etc/ssl/qcode/cryptpad.qcode.ch.crt;
|
||||
ssl_certificate_key /etc/ssl/qcode/cryptpad.qcode.ch.key;
|
||||
|
||||
ssl_dhparam /etc/nginx/snippets/dhparam; # openssl dhparam -out /etc/nginx/dhparam.pem 4096
|
||||
ssl_session_timeout 5m;
|
||||
ssl_session_cache shared:cryptpadSSL:5m;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
# https://cipherli.st/
|
||||
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
|
||||
ssl_ecdh_curve secp384r1;
|
||||
|
||||
# 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 "cryptpad.qcode.ch";
|
||||
set $sandbox_domain "cryptpad.qcodecdn.ch";
|
||||
|
||||
# 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 "cryptpad.qcode.ch";
|
||||
#set $files_domain "files.your-main-domain.com";
|
||||
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
|
||||
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";
|
||||
|
||||
# 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/cryptpad/static;
|
||||
index index.html;
|
||||
#error_page 404 customize/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;
|
||||
}
|
||||
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 ^~ /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/ {
|
||||
root /home/cryptpad/data;
|
||||
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 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 X-Content-Type-Options nosniff;
|
||||
add_header Cache-Control max-age=31536000;
|
||||
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';
|
||||
}
|
||||
|
||||
# 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/ {
|
||||
root /home/cryptpad/data;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header Cache-Control max-age=0;
|
||||
}
|
||||
|
||||
# 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)$ {
|
||||
return 301 https://${main_domain}/$1/;
|
||||
}
|
||||
|
||||
# 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;
|
||||
#try_files /customize/$1 /customize.dist/$1 =404;
|
||||
}
|
||||
location ^~ /customize.dist/ {
|
||||
# simply serve static files from root
|
||||
}
|
||||
|
||||
# Finally, serve anything the above exceptions don't govern.
|
||||
try_files /www/$uri /www/$uri/index.html /customize/$uri;
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
A custom self-hosted instance of [CryptPad](https://cryptpad.fr/) for qcode
|
||||
infra, accessible at https://cryptpad.qcode.ch.
|
||||
|
||||
The upstream code lives in the [cryptpad](cryptpad/) sub directory. This
|
||||
is placed as a git subtree, not to be confused with submodule. To customize
|
||||
functionality or look&feel, copy a file from
|
||||
[cryptpad/customize.dist](cryptpad/customize.dist/) into
|
||||
[customize](customize/) and change it. The file will be served in place of
|
||||
the original dist.
|
||||
|
||||
See [upstream docs](https://docs.cryptpad.fr/en/admin_guide/customization.html)
|
||||
for customization details.
|
||||
|
||||
## Updating from upstream
|
||||
|
||||
Check the current status of the local cryptpad copy with:
|
||||
|
||||
git log cryptpad
|
||||
|
||||
Then go to https://github.com/xwiki-labs/cryptpad/commits/main and check where
|
||||
the upstream is at.
|
||||
|
||||
To update local copy with upstream changes, use
|
||||
[tools/pull-cryptpad-upstream.sh](tools/pull-cryptpad-upstream.sh) script.
|
||||
For example, to pull up to an imaginary release tag xyz, execute:
|
||||
|
||||
./tools/pull-cryptpad-upstream.sh xyz
|
||||
|
||||
It'll fetch from upstream and add new commits as if they were part of this repo.
|
||||
Finally, `git push` to update this repo's remote.
|
||||
|
||||
If instead you want to make a pull request, first create a branch. Something like
|
||||
`git checkout -b upstream-update-xyz master` should do. Then execute the above
|
||||
script and send the branch as a pull request.
|
||||
|
||||
For the record, initial subtree merge from upstream was done with the following
|
||||
command:
|
||||
|
||||
git subtree add -P cryptpad https://github.com/xwiki-labs/cryptpad.git 4.14.0
|
||||
|
||||
## Contributing to upstream
|
||||
|
||||
You'll probably want to have a separate repository, cloned directly from the
|
||||
upstream `https://github.com/xwiki-labs/cryptpad.git`. Since this repo's
|
||||
cryptpad dir is a copy of the upstream repo, it should be very easy to apply
|
||||
changes to both using patch files and `git apply` or `patch` commands.
|
||||
|
||||
See details on [how to contribute](https://docs.cryptpad.fr/en/how_to_contribute.html)
|
||||
in the upstream docs.
|
||||
|
||||
## Dev environment
|
||||
|
||||
To start a local dev instance, forget about the files in the root of this repo
|
||||
and simply work in the [cryptpad](cryptpad/) sub directory. In other words,
|
||||
follow [upstream dev guide](https://docs.cryptpad.fr/en/dev_guide/setup.html).
|
||||
|
||||
When done, a `git diff` will show some changes. Those in the `cryptpad/` sub
|
||||
directory should go to upstream. Anything else, notably the [customize](customize/)
|
||||
directory, lives in this repo.
|
||||
|
||||
## Production instance
|
||||
|
||||
To build for prod deployment, you'll need [podman](https://podman.io).
|
||||
Create prod build artifacts manually with:
|
||||
|
||||
./tools/build-prod.sh
|
||||
|
||||
The script creates few files in the `build` directory. Notably, the two files
|
||||
required for prod deployment are:
|
||||
|
||||
- `cryptpad-container-img-<git-commit-hash>.tar.gz`: container file with
|
||||
the nodejs server
|
||||
- `cryptpad-static-<git-commit-hash>.tar.gz`: static files served by
|
||||
nginx frontend
|
||||
|
||||
Copy both files to production machines. The `cryptpad-container-img.tar.gz` can
|
||||
be loaded on the machine with:
|
||||
|
||||
podman load path/to/cryptpad-container-img.tar.gz
|
||||
|
||||
Unpack the static files into a temp dir and sync with the prod dir:
|
||||
|
||||
rsync -rl --chown root:root --delete-after tmpdir/ path/to/proddir/
|
||||
|
||||
There are also a couple of config files, `config.js` and `nginx.conf`, in the root
|
||||
of this repo. These are production configs and will eventually move to
|
||||
another location with all the other prod infra configs.
|
||||
|
||||
All the manual steps described above will disappear once a central prod infra
|
||||
is in place.
|
@ -0,0 +1,47 @@
|
||||
#!/bin/sh -e
|
||||
PODMAN=podman
|
||||
if ! type podman > /dev/null; then
|
||||
printf "$0 requires podman; see https://podman.io\n" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
cd $(dirname $0)/..
|
||||
|
||||
# all build artifacts are stored with this version suffix
|
||||
VERSION=$(git rev-parse --short HEAD)
|
||||
mkdir -p build
|
||||
|
||||
# cryptpad's node server needs a couple files from www/common.
|
||||
# it also needs 404.html and 500.html from customize[.dist], otherwise
|
||||
# the express server hogs CPU at 100% if a request hits a nonexistent file.
|
||||
# the customize dir must be mounted in read-only at container start.
|
||||
tar -cf build/bootstrap.tar \
|
||||
-C cryptpad \
|
||||
.bowerrc \
|
||||
bower.json \
|
||||
lib \
|
||||
package-lock.json \
|
||||
package.json \
|
||||
scripts \
|
||||
server.js \
|
||||
LICENSE
|
||||
mkdir -p cryptpad/www/bower_components
|
||||
$PODMAN build --rm --squash --net=host \
|
||||
-v $PWD/cryptpad/www/bower_components:/build/www/bower_components \
|
||||
-t cryptpad .
|
||||
$PODMAN save cryptpad | gzip > build/cryptpad-container-img-$VERSION.tar.gz
|
||||
|
||||
# static files served by an HTTP frontend, as well as the customize dir
|
||||
# required by the node server run in a container image.
|
||||
STATIC_TAR_OUT=build/cryptpad-static-$VERSION.tar
|
||||
tar -cf $STATIC_TAR_OUT \
|
||||
-C cryptpad \
|
||||
customize.dist \
|
||||
www \
|
||||
LICENSE
|
||||
# append custom files, in a separate step to preserve desired file
|
||||
# tree structure.
|
||||
tar -rf $STATIC_TAR_OUT customize
|
||||
printf "${VERSION}" > build/commit.txt
|
||||
tar -rf $STATIC_TAR_OUT -C build commit.txt
|
||||
# finally, gzip the archive for faster transfer/deployment.
|
||||
gzip -f $STATIC_TAR_OUT
|
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
REPO="https://github.com/xwiki-labs/cryptpad.git"
|
||||
PREFIX=cryptpad
|
||||
REF="${1}"
|
||||
if [ -z "${ref}" ]; then
|
||||
printf "usage: $0 <ref>\n" 1>&2
|
||||
printf "ref: main, tag, branch or commit hash\n" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
cd $(dirname $0)/..
|
||||
exec git subtree pull -P "${PREFIX}" "${REPO}" "${REF}"
|
Loading…
Reference in New Issue