Merge branch 'small-config' into staging
This commit is contained in:
@@ -1,67 +1,110 @@
|
|||||||
/*
|
/* globals module */
|
||||||
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
|
||||||
|
|
||||||
*/
|
*/
|
||||||
var _domain = 'http://localhost:3000/';
|
|
||||||
|
|
||||||
// You can `kill -USR2` the node process and it will write out a heap dump.
|
|
||||||
// If your system doesn't support dumping, comment this out and install with
|
|
||||||
// `npm install --production`
|
|
||||||
// See: https://strongloop.github.io/strongloop.com/strongblog/how-to-heap-snapshots/
|
|
||||||
|
|
||||||
// to enable this feature, uncomment the line below:
|
|
||||||
// require('heapdump');
|
|
||||||
|
|
||||||
// we prepend a space because every usage expects it
|
|
||||||
// requiring admins to preserve it is unnecessarily confusing
|
|
||||||
var domain = ' ' + _domain;
|
|
||||||
|
|
||||||
// Content-Security-Policy
|
|
||||||
var baseCSP = [
|
|
||||||
"default-src 'none'",
|
|
||||||
"style-src 'unsafe-inline' 'self' " + domain,
|
|
||||||
"font-src 'self' data:" + domain,
|
|
||||||
|
|
||||||
/* child-src is used to restrict iframes to a set of allowed domains.
|
|
||||||
* connect-src is used to restrict what domains can connect to the websocket.
|
|
||||||
*
|
|
||||||
* it is recommended that you configure these fields to match the
|
|
||||||
* domain which will serve your CryptPad instance.
|
|
||||||
*/
|
|
||||||
"child-src blob: *",
|
|
||||||
// IE/Edge
|
|
||||||
"frame-src blob: *",
|
|
||||||
|
|
||||||
/* this allows connections over secure or insecure websockets
|
|
||||||
if you are deploying to production, you'll probably want to remove
|
|
||||||
the ws://* directive, and change '*' to your domain
|
|
||||||
*/
|
|
||||||
"connect-src 'self' ws: wss: blob:" + domain,
|
|
||||||
|
|
||||||
// data: is used by codemirror
|
|
||||||
"img-src 'self' data: blob:" + domain,
|
|
||||||
"media-src * blob:",
|
|
||||||
|
|
||||||
// for accounts.cryptpad.fr authentication and cross-domain iframe sandbox
|
|
||||||
"frame-ancestors *",
|
|
||||||
""
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
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 handled by NGINX, as documented in
|
||||||
|
* cryptpad/docs/example.nginx.conf (see the $main_domain variable)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
httpUnsafeOrigin: 'http://localhost:3000/',
|
||||||
|
|
||||||
|
/* 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://some-other-domain.xyz",
|
||||||
|
|
||||||
|
/* 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: '::',
|
||||||
|
|
||||||
|
/* 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,
|
||||||
|
|
||||||
/* =====================
|
/* =====================
|
||||||
* Admin
|
* Admin
|
||||||
* ===================== */
|
* ===================== */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CryptPad now contains an administration panel. Its access is restricted to specific
|
* CryptPad contains an administration panel. Its access is restricted to specific
|
||||||
* users using the following list.
|
* users using the following list.
|
||||||
* To give access to the admin panel to a user account, just add their user id,
|
* To give access to the admin panel to a user account, just add their user id,
|
||||||
* which can be found on the settings page for registered users.
|
* which can be found on the settings page for registered users.
|
||||||
* Entries should be strings separated by a comma.
|
* Entries should be strings separated by a comma.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
adminKeys: [
|
adminKeys: [
|
||||||
//"https://my.awesome.website/user/#/1/cryptpad-user1/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=",
|
//"https://my.awesome.website/user/#/1/cryptpad-user1/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=",
|
||||||
],
|
],
|
||||||
|
*/
|
||||||
|
|
||||||
/* CryptPad's administration panel includes a "support" tab
|
/* CryptPad's administration panel includes a "support" tab
|
||||||
* wherein administrators with a secret key can view messages
|
* wherein administrators with a secret key can view messages
|
||||||
@@ -76,159 +119,55 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
// supportMailboxPublicKey: "",
|
// supportMailboxPublicKey: "",
|
||||||
|
|
||||||
/* =====================
|
/* We're very proud that CryptPad is available to the public as free software!
|
||||||
* Infra setup
|
* We do, however, still need to pay our bills as we develop the platform.
|
||||||
* ===================== */
|
|
||||||
|
|
||||||
// the address you want to bind to, :: means all ipv4 and ipv6 addresses
|
|
||||||
// this may not work on all operating systems
|
|
||||||
httpAddress: '::',
|
|
||||||
|
|
||||||
// the port on which your httpd will listen
|
|
||||||
httpPort: 3000,
|
|
||||||
|
|
||||||
// This is for allowing the cross-domain iframe to function when developing
|
|
||||||
httpSafePort: 3001,
|
|
||||||
|
|
||||||
// This is for deployment in production, CryptPad uses a separate origin (domain) to host the
|
|
||||||
// cross-domain iframe. It can simply host the same content as CryptPad.
|
|
||||||
// httpSafeOrigin: "https://some-other-domain.xyz",
|
|
||||||
|
|
||||||
httpUnsafeOrigin: domain,
|
|
||||||
|
|
||||||
/* Your CryptPad server will share this value with clients
|
|
||||||
* via its /api/config endpoint.
|
|
||||||
*
|
*
|
||||||
* If you want to host your API and asset servers on different hosts
|
* By default CryptPad will prompt users to consider donating to
|
||||||
* specify a URL for your API server websocket endpoint, like so:
|
* our OpenCollective campaign. We publish the state of our finances periodically
|
||||||
* wss://api.yourdomain.com/cryptpad_websocket
|
* so you can decide for yourself whether our expenses are reasonable.
|
||||||
*
|
*
|
||||||
* Otherwise, leave this commented and your clients will use the default
|
* You can disable any solicitations for donations by setting 'removeDonateButton' to true,
|
||||||
* websocket (wss://yourdomain.com/cryptpad_websocket)
|
* but we'd appreciate it if you didn't!
|
||||||
*/
|
*/
|
||||||
//externalWebsocketURL: 'wss://api.yourdomain.com/cryptpad_websocket
|
//removeDonateButton: false,
|
||||||
|
|
||||||
/* CryptPad can be configured to send customized HTTP Headers
|
/* CryptPad will display a point of contact for your instance on its contact page
|
||||||
* These settings may vary widely depending on your needs
|
* (/contact.html) if you provide it below.
|
||||||
* Examples are provided below
|
|
||||||
*/
|
|
||||||
httpHeaders: {
|
|
||||||
"X-XSS-Protection": "1; mode=block",
|
|
||||||
"X-Content-Type-Options": "nosniff",
|
|
||||||
"Access-Control-Allow-Origin": "*"
|
|
||||||
},
|
|
||||||
|
|
||||||
contentSecurity: baseCSP.join('; ') +
|
|
||||||
"script-src 'self'" + domain,
|
|
||||||
|
|
||||||
// CKEditor and OnlyOffice require significantly more lax content security policy in order to function.
|
|
||||||
padContentSecurity: baseCSP.join('; ') +
|
|
||||||
"script-src 'self' 'unsafe-eval' 'unsafe-inline'" + domain,
|
|
||||||
|
|
||||||
/* Main pages
|
|
||||||
* add exceptions to the router so that we can access /privacy.html
|
|
||||||
* and other odd pages
|
|
||||||
*/
|
|
||||||
mainPages: [
|
|
||||||
'index',
|
|
||||||
'privacy',
|
|
||||||
'terms',
|
|
||||||
'about',
|
|
||||||
'contact',
|
|
||||||
'what-is-cryptpad',
|
|
||||||
'features',
|
|
||||||
'faq',
|
|
||||||
'maintenance'
|
|
||||||
],
|
|
||||||
|
|
||||||
/* =====================
|
|
||||||
* Subscriptions
|
|
||||||
* ===================== */
|
|
||||||
|
|
||||||
/* Limits, Donations, Subscriptions and Contact
|
|
||||||
*
|
|
||||||
* By default, CryptPad limits every registered user to 50MB of storage. It also shows a
|
|
||||||
* subscribe button which allows them to upgrade to a paid account. We handle payment,
|
|
||||||
* and keep 50% of the proceeds to fund ongoing development.
|
|
||||||
*
|
|
||||||
* You can:
|
|
||||||
* A: leave things as they are
|
|
||||||
* B: disable accounts but display a donate button
|
|
||||||
* C: hide any reference to paid accounts or donation
|
|
||||||
*
|
|
||||||
* If you chose A then there's nothing to do.
|
|
||||||
* If you chose B, set 'allowSubscriptions' to false.
|
|
||||||
* If you chose C, set 'removeDonateButton' to true
|
|
||||||
*/
|
|
||||||
allowSubscriptions: true,
|
|
||||||
removeDonateButton: false,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* By default, CryptPad also contacts our accounts server once a day to check for changes in
|
|
||||||
* the people who have accounts. This check-in will also send the version of your CryptPad
|
|
||||||
* instance and your email so we can reach you if we are aware of a serious problem. We will
|
|
||||||
* never sell it or send you marketing mail. If you want to block this check-in and remain
|
|
||||||
* completely invisible, set this and allowSubscriptions both to false.
|
|
||||||
*/
|
*/
|
||||||
adminEmail: 'i.did.not.read.my.config@cryptpad.fr',
|
adminEmail: 'i.did.not.read.my.config@cryptpad.fr',
|
||||||
|
|
||||||
/* Sales coming from your server will be identified by your domain
|
/*
|
||||||
|
* By default, CryptPad contacts one of our servers once a day.
|
||||||
|
* This check-in will also send some very basic information about your instance including its
|
||||||
|
* version and the adminEmail so we can reach you if we are aware of a serious problem.
|
||||||
|
* We will never sell it or send you marketing mail.
|
||||||
*
|
*
|
||||||
* If you are using CryptPad in a business context, please consider taking a support contract
|
* If you want to block this check-in and remain set 'blockDailyCheck' to true.
|
||||||
* by contacting sales@cryptpad.fr
|
|
||||||
*/
|
*/
|
||||||
myDomain: _domain,
|
//blockDailyCheck: false,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If you are using CryptPad internally and you want to increase the per-user storage limit,
|
* By default users get 50MB of storage by registering on an instance.
|
||||||
* change the following value.
|
* You can set this value to whatever you want.
|
||||||
*
|
*
|
||||||
* Please note: This limit is what makes people subscribe and what pays for CryptPad
|
* hint: 50MB is 50 * 1024 * 1024
|
||||||
* development. Running a public instance that provides a "better deal" than cryptpad.fr
|
|
||||||
* is effectively using the project against itself.
|
|
||||||
*/
|
*/
|
||||||
defaultStorageLimit: 50 * 1024 * 1024,
|
//defaultStorageLimit: 50 * 1024 * 1024,
|
||||||
|
|
||||||
/*
|
|
||||||
* CryptPad allows administrators to give custom limits to their friends.
|
|
||||||
* add an entry for each friend, identified by their user id,
|
|
||||||
* which can be found on the settings page. Include a 'limit' (number of bytes),
|
|
||||||
* a 'plan' (string), and a 'note' (string).
|
|
||||||
*
|
|
||||||
* hint: 1GB is 1024 * 1024 * 1024 bytes
|
|
||||||
*/
|
|
||||||
customLimits: {
|
|
||||||
/*
|
|
||||||
"https://my.awesome.website/user/#/1/cryptpad-user1/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=": {
|
|
||||||
limit: 20 * 1024 * 1024 * 1024,
|
|
||||||
plan: 'insider',
|
|
||||||
note: 'storage space donated by my.awesome.website'
|
|
||||||
},
|
|
||||||
"https://my.awesome.website/user/#/1/cryptpad-user2/GdflkgdlkjeworijfkldfsdflkjeEAsdlEnkbx1vVOo=": {
|
|
||||||
limit: 10 * 1024 * 1024 * 1024,
|
|
||||||
plan: 'insider',
|
|
||||||
note: 'storage space donated by my.awesome.website'
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
},
|
|
||||||
|
|
||||||
/* =====================
|
/* =====================
|
||||||
* STORAGE
|
* STORAGE
|
||||||
* ===================== */
|
* ===================== */
|
||||||
|
|
||||||
/* By default the CryptPad server will run scheduled tasks every five minutes
|
|
||||||
* If you want to run scheduled tasks in a separate process (like a crontab)
|
|
||||||
* you can disable this behaviour by setting the following value to true
|
|
||||||
*/
|
|
||||||
disableIntegratedTasks: false,
|
|
||||||
|
|
||||||
/* Pads that are not 'pinned' by any registered user can be set to expire
|
/* 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).
|
* after a configurable number of days of inactivity (default 90 days).
|
||||||
* The value can be changed or set to false to remove expiration.
|
* The value can be changed or set to false to remove expiration.
|
||||||
* Expired pads can then be removed using a cron job calling the
|
* Expired pads can then be removed using a cron job calling the
|
||||||
* `delete-inactive.js` script with node
|
* `evict-inactive.js` script with node
|
||||||
|
*
|
||||||
|
* defaults to 90 days if nothing is provided
|
||||||
*/
|
*/
|
||||||
inactiveTime: 90, // days
|
//inactiveTime: 90, // days
|
||||||
|
|
||||||
/* CryptPad archives some data instead of deleting it outright.
|
/* CryptPad archives some data instead of deleting it outright.
|
||||||
* This archived data still takes up space and so you'll probably still want to
|
* This archived data still takes up space and so you'll probably still want to
|
||||||
@@ -241,31 +180,46 @@ module.exports = {
|
|||||||
* deletion. Set this value to the number of days you'd like to retain
|
* deletion. Set this value to the number of days you'd like to retain
|
||||||
* archived data before it's removed permanently.
|
* archived data before it's removed permanently.
|
||||||
*
|
*
|
||||||
|
* defaults to 15 days if nothing is provided
|
||||||
*/
|
*/
|
||||||
archiveRetentionTime: 15,
|
//archiveRetentionTime: 15,
|
||||||
|
|
||||||
/* Max Upload Size (bytes)
|
/* Max Upload Size (bytes)
|
||||||
* this sets the maximum size of any one file uploaded to the server.
|
* this sets the maximum size of any one file uploaded to the server.
|
||||||
* anything larger than this size will be rejected
|
* anything larger than this size will be rejected
|
||||||
|
* defaults to 20MB if no value is provided
|
||||||
*/
|
*/
|
||||||
maxUploadSize: 20 * 1024 * 1024,
|
//maxUploadSize: 20 * 1024 * 1024,
|
||||||
|
|
||||||
// XXX
|
/*
|
||||||
premiumUploadSize: 100 * 1024 * 1024,
|
* CryptPad allows administrators to give custom limits to their friends.
|
||||||
|
* add an entry for each friend, identified by their user id,
|
||||||
/* =====================
|
* which can be found on the settings page. Include a 'limit' (number of bytes),
|
||||||
* HARDWARE RELATED
|
* a 'plan' (string), and a 'note' (string).
|
||||||
* ===================== */
|
*
|
||||||
|
* hint: 1GB is 1024 * 1024 * 1024 bytes
|
||||||
/* CryptPad's file storage adaptor closes unused files after a configurable
|
|
||||||
* number of milliseconds (default 30000 (30 seconds))
|
|
||||||
*/
|
*/
|
||||||
channelExpirationMs: 30000,
|
/*
|
||||||
|
customLimits: {
|
||||||
|
"https://my.awesome.website/user/#/1/cryptpad-user1/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=": {
|
||||||
|
limit: 20 * 1024 * 1024 * 1024,
|
||||||
|
plan: 'insider',
|
||||||
|
note: 'storage space donated by my.awesome.website'
|
||||||
|
},
|
||||||
|
"https://my.awesome.website/user/#/1/cryptpad-user2/GdflkgdlkjeworijfkldfsdflkjeEAsdlEnkbx1vVOo=": {
|
||||||
|
limit: 10 * 1024 * 1024 * 1024,
|
||||||
|
plan: 'insider',
|
||||||
|
note: 'storage space donated by my.awesome.website'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
/* CryptPad's file storage adaptor is limited by the number of open files.
|
/* Users with premium accounts (those with a plan included in their customLimit)
|
||||||
* When the adaptor reaches openFileLimit, it will clean up older files
|
* can benefit from an increased upload size limit. By default they are restricted to the same
|
||||||
|
* upload size as any other registered user.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
openFileLimit: 2048,
|
//premiumUploadSize: 100 * 1024 * 1024,
|
||||||
|
|
||||||
/* =====================
|
/* =====================
|
||||||
* DATABASE VOLUMES
|
* DATABASE VOLUMES
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ Quota.updateCachedLimits = function (Env, cb) {
|
|||||||
if (Env.adminEmail === false) {
|
if (Env.adminEmail === false) {
|
||||||
Quota.applyCustomLimits(Env);
|
Quota.applyCustomLimits(Env);
|
||||||
if (Env.allowSubscriptions === false) { return; }
|
if (Env.allowSubscriptions === false) { return; }
|
||||||
|
if (Env.blockDailyCheck === true) { return; }
|
||||||
throw new Error("allowSubscriptions must be false if adminEmail is false");
|
throw new Error("allowSubscriptions must be false if adminEmail is false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
86
lib/defaults.js
Normal file
86
lib/defaults.js
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
var Default = module.exports;
|
||||||
|
|
||||||
|
Default.commonCSP = function (domain) {
|
||||||
|
domain = ' ' + domain;
|
||||||
|
// Content-Security-Policy
|
||||||
|
|
||||||
|
return [
|
||||||
|
"default-src 'none'",
|
||||||
|
"style-src 'unsafe-inline' 'self' " + domain,
|
||||||
|
"font-src 'self' data:" + domain,
|
||||||
|
|
||||||
|
/* child-src is used to restrict iframes to a set of allowed domains.
|
||||||
|
* connect-src is used to restrict what domains can connect to the websocket.
|
||||||
|
*
|
||||||
|
* it is recommended that you configure these fields to match the
|
||||||
|
* domain which will serve your CryptPad instance.
|
||||||
|
*/
|
||||||
|
"child-src blob: *",
|
||||||
|
// IE/Edge
|
||||||
|
"frame-src blob: *",
|
||||||
|
|
||||||
|
/* this allows connections over secure or insecure websockets
|
||||||
|
if you are deploying to production, you'll probably want to remove
|
||||||
|
the ws://* directive, and change '*' to your domain
|
||||||
|
*/
|
||||||
|
"connect-src 'self' ws: wss: blob:" + domain,
|
||||||
|
|
||||||
|
// data: is used by codemirror
|
||||||
|
"img-src 'self' data: blob:" + domain,
|
||||||
|
"media-src * blob:",
|
||||||
|
|
||||||
|
// for accounts.cryptpad.fr authentication and cross-domain iframe sandbox
|
||||||
|
"frame-ancestors *",
|
||||||
|
""
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
Default.contentSecurity = function (domain) {
|
||||||
|
return (Default.commonCSP(domain).join('; ') + "script-src 'self' " + domain).replace(/\s+/g, ' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
Default.padContentSecurity = function (domain) {
|
||||||
|
return (Default.commonCSP(domain).join('; ') + "script-src 'self' 'unsafe-eval' 'unsafe-inline' " + domain).replace(/\s+/g, ' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
Default.httpHeaders = function () {
|
||||||
|
return {
|
||||||
|
"X-XSS-Protection": "1; mode=block",
|
||||||
|
"X-Content-Type-Options": "nosniff",
|
||||||
|
"Access-Control-Allow-Origin": "*"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Default.mainPages = function () {
|
||||||
|
return [
|
||||||
|
'index',
|
||||||
|
'privacy',
|
||||||
|
'terms',
|
||||||
|
'about',
|
||||||
|
'contact',
|
||||||
|
'what-is-cryptpad',
|
||||||
|
'features',
|
||||||
|
'faq',
|
||||||
|
'maintenance'
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* By default the CryptPad server will run scheduled tasks every five minutes
|
||||||
|
* If you want to run scheduled tasks in a separate process (like a crontab)
|
||||||
|
* you can disable this behaviour by setting the following value to true
|
||||||
|
*/
|
||||||
|
//disableIntegratedTasks: false,
|
||||||
|
|
||||||
|
/* CryptPad's file storage adaptor closes unused files after a configurable
|
||||||
|
* number of milliseconds (default 30000 (30 seconds))
|
||||||
|
*/
|
||||||
|
// channelExpirationMs: 30000,
|
||||||
|
|
||||||
|
/* CryptPad's file storage adaptor is limited by the number of open files.
|
||||||
|
* When the adaptor reaches openFileLimit, it will clean up older files
|
||||||
|
*/
|
||||||
|
//openFileLimit: 2048,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -65,10 +65,13 @@ module.exports.create = function (config, cb) {
|
|||||||
WARN: WARN,
|
WARN: WARN,
|
||||||
flushCache: config.flushCache,
|
flushCache: config.flushCache,
|
||||||
adminEmail: config.adminEmail,
|
adminEmail: config.adminEmail,
|
||||||
allowSubscriptions: config.allowSubscriptions,
|
allowSubscriptions: config.allowSubscriptions === true,
|
||||||
myDomain: config.myDomain,
|
blockDailyCheck: config.blockDailyCheck === true,
|
||||||
|
|
||||||
|
myDomain: config.httpUnsafeOrigin,
|
||||||
|
// XXX not included in the config...
|
||||||
mySubdomain: config.mySubdomain,
|
mySubdomain: config.mySubdomain,
|
||||||
customLimits: config.customLimits,
|
customLimits: config.customLimits || {},
|
||||||
// FIXME this attribute isn't in the default conf
|
// FIXME this attribute isn't in the default conf
|
||||||
// but it is referenced in Quota
|
// but it is referenced in Quota
|
||||||
domain: config.domain
|
domain: config.domain
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
"use strict";
|
"use strict";
|
||||||
var config;
|
var config;
|
||||||
var configPath = process.env.CRYPTPAD_CONFIG || "../config/config";
|
var configPath = process.env.CRYPTPAD_CONFIG || "../config/config.js";
|
||||||
try {
|
try {
|
||||||
config = require(configPath);
|
config = require(configPath);
|
||||||
if (config.adminEmail === 'i.did.not.read.my.config@cryptpad.fr') {
|
if (config.adminEmail === 'i.did.not.read.my.config@cryptpad.fr') {
|
||||||
@@ -18,5 +18,23 @@ try {
|
|||||||
}
|
}
|
||||||
config = require("../config/config.example");
|
config = require("../config/config.example");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPositiveNumber = function (n) {
|
||||||
|
return (!isNaN(n) && n >= 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!isPositiveNumber(config.inactiveTime)) {
|
||||||
|
config.inactiveTime = 90;
|
||||||
|
}
|
||||||
|
if (!isPositiveNumber(config.archiveRetentionTime)) {
|
||||||
|
config.archiveRetentionTime = 90;
|
||||||
|
}
|
||||||
|
if (!isPositiveNumber(config.maxUploadSize)) {
|
||||||
|
config.maxUploadSize = 20 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
if (!isPositiveNumber(config.defaultStorageLimit)) {
|
||||||
|
config.defaultStorageLimit = 50 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ var Config = require("../lib/load-config");
|
|||||||
var Package = require("../package.json");
|
var Package = require("../package.json");
|
||||||
|
|
||||||
var body = JSON.stringify({
|
var body = JSON.stringify({
|
||||||
domain: Config.myDomain,
|
domain: Config.myDomain || Config.httpUnsafeOrigin,
|
||||||
subdomain: Config.mySubdomain || null,
|
subdomain: Config.mySubdomain || null,
|
||||||
adminEmail: Config.adminEmail,
|
adminEmail: Config.adminEmail,
|
||||||
version: Package.version,
|
version: Package.version,
|
||||||
|
|||||||
74
server.js
74
server.js
@@ -8,6 +8,7 @@ var Package = require('./package.json');
|
|||||||
var Path = require("path");
|
var Path = require("path");
|
||||||
var nThen = require("nthen");
|
var nThen = require("nthen");
|
||||||
var Util = require("./lib/common-util");
|
var Util = require("./lib/common-util");
|
||||||
|
var Default = require("./lib/defaults");
|
||||||
|
|
||||||
var config = require("./lib/load-config");
|
var config = require("./lib/load-config");
|
||||||
|
|
||||||
@@ -35,6 +36,47 @@ if (process.env.PACKAGE) {
|
|||||||
FRESH_KEY = +new Date();
|
FRESH_KEY = +new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
// you absolutely must provide an 'httpUnsafeOrigin'
|
||||||
|
if (typeof(config.httpUnsafeOrigin) !== 'string') {
|
||||||
|
throw new Error("No 'httpUnsafeOrigin' provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
config.httpUnsafeOrigin = config.httpUnsafeOrigin.trim();
|
||||||
|
|
||||||
|
// fall back to listening on a local address
|
||||||
|
// if httpAddress is not a string
|
||||||
|
if (typeof(config.httpAddress) !== 'string') {
|
||||||
|
config.httpAddress = '127.0.0.1';
|
||||||
|
}
|
||||||
|
|
||||||
|
// listen on port 3000 if a valid port number was not provided
|
||||||
|
if (typeof(config.httpPort) !== 'number' || config.httpPort > 65535) {
|
||||||
|
config.httpPort = 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(httpSafeOrigin) !== 'string') {
|
||||||
|
if (typeof(config.httpSafePort) !== 'number') {
|
||||||
|
config.httpSafePort = config.httpPort + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEV_MODE) { return; }
|
||||||
|
console.log(`
|
||||||
|
m m mm mmmmm mm m mmmmm mm m mmm m
|
||||||
|
# # # ## # "# #"m # # #"m # m" " #
|
||||||
|
" #"# # # # #mmmm" # #m # # # #m # # mm #
|
||||||
|
## ##" #mm# # "m # # # # # # # # #
|
||||||
|
# # # # # " # ## mm#mm # ## "mmm" #
|
||||||
|
`);
|
||||||
|
|
||||||
|
console.log("\nNo 'httpSafeOrigin' provided.");
|
||||||
|
console.log("Your configuration probably isn't taking advantage of all of CryptPad's security features!");
|
||||||
|
console.log("This is acceptable for development, otherwise your users may be at risk.\n");
|
||||||
|
|
||||||
|
console.log("Serving sandboxed content via port %s.\nThis is probably not what you want for a production instance!\n", config.httpSafePort);
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
var configCache = {};
|
var configCache = {};
|
||||||
config.flushCache = function () {
|
config.flushCache = function () {
|
||||||
configCache = {};
|
configCache = {};
|
||||||
@@ -47,11 +89,21 @@ config.flushCache = function () {
|
|||||||
const clone = (x) => (JSON.parse(JSON.stringify(x)));
|
const clone = (x) => (JSON.parse(JSON.stringify(x)));
|
||||||
|
|
||||||
var setHeaders = (function () {
|
var setHeaders = (function () {
|
||||||
if (typeof(config.httpHeaders) !== 'object') { return function () {}; }
|
// load the default http headers unless the admin has provided their own via the config file
|
||||||
|
var headers;
|
||||||
|
|
||||||
const headers = clone(config.httpHeaders);
|
var custom = config.httpHeaders;
|
||||||
if (config.contentSecurity) {
|
// if the admin provided valid http headers then use them
|
||||||
headers['Content-Security-Policy'] = clone(config.contentSecurity);
|
if (custom && typeof(custom) === 'object' && !Array.isArray(custom)) {
|
||||||
|
headers = clone(custom);
|
||||||
|
} else {
|
||||||
|
// otherwise use the default
|
||||||
|
headers = Default.httpHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
// next define the base Content Security Policy (CSP) headers
|
||||||
|
if (typeof(config.contentSecurity) === 'string') {
|
||||||
|
headers['Content-Security-Policy'] = config.contentSecurity;
|
||||||
if (!/;$/.test(headers['Content-Security-Policy'])) { headers['Content-Security-Policy'] += ';' }
|
if (!/;$/.test(headers['Content-Security-Policy'])) { headers['Content-Security-Policy'] += ';' }
|
||||||
if (headers['Content-Security-Policy'].indexOf('frame-ancestors') === -1) {
|
if (headers['Content-Security-Policy'].indexOf('frame-ancestors') === -1) {
|
||||||
// backward compat for those who do not merge the new version of the config
|
// backward compat for those who do not merge the new version of the config
|
||||||
@@ -59,10 +111,16 @@ var setHeaders = (function () {
|
|||||||
// It also fixes the cross-domain iframe.
|
// It also fixes the cross-domain iframe.
|
||||||
headers['Content-Security-Policy'] += "frame-ancestors *;";
|
headers['Content-Security-Policy'] += "frame-ancestors *;";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// use the default CSP headers constructed with your domain
|
||||||
|
headers['Content-Security-Policy'] = Default.contentSecurity(config.httpUnsafeOrigin);
|
||||||
}
|
}
|
||||||
|
|
||||||
const padHeaders = clone(headers);
|
const padHeaders = clone(headers);
|
||||||
if (config.padContentSecurity) {
|
if (typeof(config.padContentSecurity) === 'string') {
|
||||||
padHeaders['Content-Security-Policy'] = clone(config.padContentSecurity);
|
padHeaders['Content-Security-Policy'] = config.padContentSecurity;
|
||||||
|
} else {
|
||||||
|
padHeaders['Content-Security-Policy'] = Default.padContentSecurity(config.httpUnsafeOrigin);
|
||||||
}
|
}
|
||||||
if (Object.keys(headers).length) {
|
if (Object.keys(headers).length) {
|
||||||
return function (req, res) {
|
return function (req, res) {
|
||||||
@@ -116,7 +174,7 @@ app.use(Express.static(__dirname + '/www'));
|
|||||||
// FIXME I think this is a regression caused by a recent PR
|
// FIXME I think this is a regression caused by a recent PR
|
||||||
// correct this hack without breaking the contributor's intended behaviour.
|
// correct this hack without breaking the contributor's intended behaviour.
|
||||||
|
|
||||||
var mainPages = config.mainPages || ['index', 'privacy', 'terms', 'about', 'contact'];
|
var mainPages = config.mainPages || Default.mainPages();
|
||||||
var mainPagePattern = new RegExp('^\/(' + mainPages.join('|') + ').html$');
|
var mainPagePattern = new RegExp('^\/(' + mainPages.join('|') + ').html$');
|
||||||
app.get(mainPagePattern, Express.static(__dirname + '/customize'));
|
app.get(mainPagePattern, Express.static(__dirname + '/customize'));
|
||||||
app.get(mainPagePattern, Express.static(__dirname + '/customize.dist'));
|
app.get(mainPagePattern, Express.static(__dirname + '/customize.dist'));
|
||||||
@@ -163,7 +221,7 @@ var serveConfig = (function () {
|
|||||||
removeDonateButton: (config.removeDonateButton === true),
|
removeDonateButton: (config.removeDonateButton === true),
|
||||||
allowSubscriptions: (config.allowSubscriptions === true),
|
allowSubscriptions: (config.allowSubscriptions === true),
|
||||||
websocketPath: config.externalWebsocketURL,
|
websocketPath: config.externalWebsocketURL,
|
||||||
httpUnsafeOrigin: config.httpUnsafeOrigin.replace(/^\s*/, ''),
|
httpUnsafeOrigin: config.httpUnsafeOrigin,
|
||||||
adminEmail: config.adminEmail,
|
adminEmail: config.adminEmail,
|
||||||
adminKeys: admins,
|
adminKeys: admins,
|
||||||
inactiveTime: config.inactiveTime,
|
inactiveTime: config.inactiveTime,
|
||||||
|
|||||||
Reference in New Issue
Block a user