Hello,
I'm having some issues with configuring Cryptpad correctly using Docker and Caddy. I know the preferred way is NGINX, I use Caddy because other stuff I run uses it and I want everything together if possible. I would really appreciate help, if possible.
Before upgrading I ran my instance with promasu/cryptpad Docker version.
/root/docker-compose/cryptpad/docker-compose.yaml:

version: '3.8'

services:
  cryptpad:
    image: "cryptpad/cryptpad:version-5.4.0"
    container_name: padinvasion
    hostname: cryptpad
    restart: always

    environment:
      - CPAD_MAIN_DOMAIN=cryptpad.mydomain.de
      - CPAD_SANDBOX_DOMAIN=sandbox.mydomain.de
      - CPAD_CONF=/cryptpad/config/config.js

    volumes:
      - /var/lib/cryptpad/data/blob:/cryptpad/blob
      - /var/lib/cryptpad/data/block:/cryptpad/block
      - /var/lib/cryptpad/customize:/cryptpad/customize
      - /var/lib/cryptpad/data/data:/cryptpad/data
      - /var/lib/cryptpad/data/files:/cryptpad/datastore
      - /var/lib/cryptpad/config.js:/cryptpad/config/config.js

    ports:
      - '3000:3000'
      - '3001:3001'
      - '3003:3003'


    ulimits:
      nofile:
        soft: 1000000
        hard: 1000000

/etc/caddy/Caddyfile:

(cryptpadheaders) {
	@safari `path_regexp('^(/|.*/|.*\\.html)$')`
	@drawio `path_regexp('^/components/drawio/src/main/webapp/index.html.*$')`
	@unsafe `path_regexp('^/unsafeiframe/inner\\.html.*$') || path_regexp('^/(sheet|doc|presentation)/inner\\.html.*$') || path_regexp('^/common/onlyoffice/./.*/.*\\.html.*$')`
	@version `path_regexp('^.*ver=.*$')`
	vars {
		default-src "default-src 'none';"
		child-src "child-src https://cryptpad.mydomain.de;"
		worker-src "worker-src 'self';"
		media-src "media-src blob:;"
		style-src "style-src 'unsafe-inline' 'self' https://cryptpad.mydomain.de;"
		script-src "script-src 'self' resource: https://cryptpad.mydomain.de;"
		connect-src "connect-src 'self' https://cryptpad.mydomain.de blob: wss://cryptpad.mydomain.de https://sandbox.mydomain.de;"
		font-src "font-src 'self' data: https://cryptpad.mydomain.de"
		image-src "image-src 'self' data: blob: https://cryptpad.mydomain.de;"
		frame-src "frame-src 'self' https://sandbox.mydomain.de blob:;"
		frame-ancestors "frame-ancestors 'self' https://cryptpad.mydomain.de"
	}
	header {
		Strict-Transport-Security "max-age=63072000; includeSubDomains" always
		X-XSS-Protection "1; mode=block"
		X-Content-Type-Options nosniff
		Access-Control-Allow-Origin "https://sandbox.mydomain.de"
		Access-Control-Allow-Credentials true
		Permissions-Policy interest-cohort=()
		Cross-Origin-Resource-Policy cross-origin
		Cross-Origin-Embedder-Policy require-corp
		Content-Security-Policy "{vars.default-src} {vars.child-src} {vars.worker-src} {vars.media-src} {vars.style-src} {vars.script-src} {vars.connect-src} {vars.font-src} {vars.image-src} {vars.frame-src} {vars.frame-ancestors}"
	}
	header @version {
		Cache-Control max-age=31536000
	}
	header @safari {
		Cache-Control no-cache
	}
	header @drawio {
		Content-Security-Policy "{vars.default-src} {vars.child-src} {vars.worker-src} {vars.media-src} {vars.style-src} script-src 'self' 'sha256-6zAB96lsBZREqf0sT44BhH1T69sm7HrN34rpMOcWbNo=' 'sha256-6g514VrT/cZFZltSaKxIVNFF46+MFaTSDTPB8WfYK+c=' resource: https://cryptpad.mydomain.de; {vars.connect-src} {vars.font-src} {vars.image-src} {vars.frame-src} {vars.frame-ancestors}"
	}
	header @unsafe {
		Content-Security-Policy "{vars.default-src} {vars.child-src} {vars.worker-src} {vars.media-src} {vars.style-src} script-src 'self' 'unsafe-eval' 'unsafe-inline' resource: https://cryptpad.mydomain.de; {vars.connect-src} {vars.font-src} {vars.image-src} {vars.fram                                                                                                                                          e-src} {vars.frame-ancestors}"
	}
}
cryptpad.mydomain.de {
	reverse_proxy 127.0.0.1:3000
#	import cryptpadheaders
}
sandbox.mydomain.de {
	reverse_proxy 127.0.0.1:3000
#	import cryptpadheaders
}

var/lib/cryptpad/config.js

/* globals module */

module.exports = {
    httpUnsafeOrigin: 'https://cryptpad.mydomain.de',
     httpSafeOrigin: 'https://sandbox.mydomain.de',
    httpAddress: '::',
     maxWorkers: 6,

    /* =====================
     *         Admin
     * ===================== */

    adminKeys: [
        "[mysupersecretkey]",
    ],
    adminEmail: 'mylikeable@email.de',
    blockDailyCheck: false,
    defaultStorageLimit: 500 * 1024 * 1024,


    /* =====================
     *        STORAGE
     * ===================== */
    inactiveTime: false, 
    archiveRetentionTime: 60,
    accountRetentionTime: false,
    disableIntegratedEviction: true,
    //maxUploadSize: 20 * 1024 * 1024,
    customLimits: {
        "[myadminaccount]": {
            limit: 20 * 1024 * 1024 * 1024,
            plan: 'insider',
            note: 'admin'
        },
      }, 
    /* =====================
     *   DATABASE VOLUMES
     * ===================== */
    filePath: './datastore/',
    archivePath: './data/archive',
    pinPath: './data/pins',
    taskPath: './data/tasks',
    blockPath: './block',
    blobPath: './blob',
    blobStagingPath: './data/blobstage',

    decreePath: './data/decrees',
    logPath: './data/logs',

    /* =====================
     *       Debugging
     * ===================== */

    logToStdout: true,
    logLevel: 'info',
    logFeedback: false,
    verbose: false,
};

I have played around with the cryptpadheaders by importing and not importing them.
When importing them I can't access anything and the headers for cryptpad.mydomain.de/drive are as follows:

HTTP/3 200 
permissions-policy: interest-cohort=()
permissions-policy: interest-cohort=()
content-type: text/html; charset=UTF-8
server: Caddy
x-content-type-options: nosniff
x-content-type-options: nosniff
content-security-policy: default-src 'none'; child-src https://cryptpad.aerturtle.de; worker-src 'self'; media-src blob:; style-src 'unsafe-inline' 'self' https://cryptpad.aerturtle.de; script-src 'self' resource: https://cryptpad.aerturtle.de; connect-src 'self' https://cryptpad.aerturtle.de blob: wss://cryptpad.aerturtle.de https://sandbox.aerturtle.de; font-src 'self' data: https://cryptpad.aerturtle.de image-src 'self' data: blob: https://cryptpad.aerturtle.de; frame-src 'self' https://sandbox.aerturtle.de blob:; frame-ancestors 'self' https://cryptpad.aerturtle.de
content-security-policy: default-src 'none'; style-src 'unsafe-inline' 'self' https://cryptpad.aerturtle.de; font-src 'self' data: https://cryptpad.aerturtle.de; child-src https://cryptpad.aerturtle.de; frame-src 'self' blob: https://sandbox.aerturtle.de; connect-src 'self' localhost blob: https://cryptpad.aerturtle.de https://cryptpad.aerturtle.de https://sandbox.aerturtle.de; img-src 'self' data: blob: https://cryptpad.aerturtle.de; media-src blob:; frame-ancestors 'self' https://cryptpad.aerturtle.de; worker-src 'self'; script-src 'self' resource: https://cryptpad.aerturtle.de
content-length: 2577
cache-control: no-cache
cache-control: no-cache
cross-origin-embedder-policy: require-corp
accept-ranges: bytes
x-xss-protection: 1; mode=block
x-xss-protection: 1; mode=block
access-control-allow-origin: https://sandbox.aerturtle.de
access-control-allow-origin: https://sandbox.aerturtle.de
date: Tue, 28 May 2024 21:31:41 GMT
x-powered-by: Express
last-modified: Tue, 28 May 2024 21:09:22 GMT
access-control-allow-credentials: true
cross-origin-resource-policy: cross-origin
cross-origin-resource-policy: cross-origin
etag: W/"a11-18fc10949c2"

Healthcheck:
Your browser was not able to load an iframe using the origin specified as httpSafeOrigin (https://sandbox.mydomain.de) in cryptpad/config/config.js. This can be caused by an invalid httpUnsafeDomain, invalid CSP configuration in your reverse proxy, invalid SSL certificates, and many other factors. More information about your particular error may be found in your browser console. Changes to cryptpad/config/config.js will require a server restart in order for /api/config to be updated.
An unexpected error occurred. See your browser's console for more detailsUnable to create, retrieve, or remove encrypted credentials from the server. This is most commonly caused by a mismatch between the value of the blockPath value configured in cryptpad/config/config.js and the corresponding settings in your reverse proxy's configuration file, but it can also be explained by a websocket error. Changes to cryptpad/config/config.js will require a server restart in order for /api/config to be updated.
Missing HTTP headers required for .xlsx export from sheets. A value of cross-origin was expected for the cross-origin-resource-policy HTTP header, but instead a value of "cross-origin, cross-origin" was received.
https://cryptpad.mydomain.de/sheet/inner.html was served with incorrect Content-Security-Policy headers.
A value of "'self' blob: https://cryptpad.mydomain.de https://sandbox.mydomain.de wss://cryptpad.mydomain.de" was expected for the connect-src directive. This rule restricts which URLs can be loaded by scripts. Overly permissive settings can allow users to be tracked using external resources, while overly restrictive settings may block pages from loading entirely.
https://cryptpad.mydomain.de/ was served with incorrect Content-Security-Policy headers.
A value of "'self' blob: https://cryptpad.mydomain.de https://sandbox.mydomain.de wss://cryptpad.mydomain.de" was expected for the connect-src directive. This rule restricts which URLs can be loaded by scripts. Overly permissive settings can allow users to be tracked using external resources, while overly restrictive settings may block pages from loading entirely.
(and so on and so forth, because they are duplicated)

When not importing my healthcheck says the following:
An unexpected error occurred. See your browser's console for more detailsUnable to create, retrieve, or remove encrypted credentials from the server. This is most commonly caused by a mismatch between the value of the blockPath value configured in cryptpad/config/config.js and the corresponding settings in your reverse proxy's configuration file, but it can also be explained by a websocket error. Changes to cryptpad/config/config.js will require a server restart in order for /api/config to be updated.
Missing HTTP headers required for .xlsx export from sheets. A value of require-corp was expected for the cross-origin-embedder-policy HTTP header, but instead a value of "" was received.
/api/config was served with duplicated or incorrect headers. Compare your reverse-proxy configuration against the provided example.
The cross-origin-resource-policy header for /api/config is '' instead of 'cross-origin' as expected.
The cross-origin-embedder-policy header for /api/config is '' instead of 'require-corp' as expected.
/api/broadcast was served with duplicated or incorrect headers. Compare your reverse-proxy configuration against the provided example.
The cross-origin-resource-policy header for /api/broadcast is '' instead of 'cross-origin' as expected.
The cross-origin-embedder-policy header for /api/broadcast is '' instead of 'require-corp' as expected.
https://cryptpad.mydomain.de/sheet/inner.html was served with incorrect Content-Security-Policy headers.
A value of "'self' blob: https://cryptpad.mydomain.de https://sandbox.mydomain.de wss://cryptpad.mydomain.de" was expected for the connect-src directive. This rule restricts which URLs can be loaded by scripts. Overly permissive settings can allow users to be tracked using external resources, while overly restrictive settings may block pages from loading entirely.
https://cryptpad.mydomain.de/ was served with incorrect Content-Security-Policy headers.
A value of "'self' blob: https://cryptpad.mydomain.de https://sandbox.mydomain.de wss://cryptpad.mydomain.de" was expected for the connect-src directive. This rule restricts which URLs can be loaded by scripts. Overly permissive settings can allow users to be tracked using external resources, while overly restrictive settings may block pages from loading entirely.
Assets must be served with a Cross-Origin-Embedder-Policy value of require-corp to enable browser features required for client-side document conversion.
This instance is not configured to require HTTP Strict Transport Security (HSTS) - which instructs clients to only interact with it over a secure connection.

I also see in the consoles a lot of objects that were not loaded from https://cryptpad.mydomain.de/bower_components/* and I'm not quite sure how to fix that and if it is important? I saw in the release notes, that it was removed, but nothing on how to fix it when using Docker

Hello,

We are no experts with Caddy, it's where a community member could chime in and provide some guidance.

However, there are multiple things that we know for sure aren't OK with your setup:

  1. Your docker-compose.yml is out of date, please refer to the one available on our GitHub repository
  2. You are trying to pass wayyyyy too much options to Caddy. Remove all that stuff and look at our Nginx example file, or if you are more familiar with HTTPd, see this community contribution
  3. Your config.js file is out-of-date, look at the latest one from our GitHub repository

Best of luck!

Mathilde changed the title to Setting headers/configuration for Docker & Caddy .

Thanks for the quick answer 🙂
I just tried upgrading it further and am now at version 5.7.0 (I'm not well versed in this, so I'm quite slow and decided to leave the Only-Office-change to future me). It honestly got much, much better with the upgrade to the basic Nginx-configuration.

These are my files at the moment. So far, everything seems to work, healthcheck still complains about HSTS. When I figure that out, I will update again. Maybe it helps someone else using Caddy.

docker-compose.yaml:

version: '3.8' 

services:
  cryptpad:
    image: "cryptpad/cryptpad:version-5.7.0"
    container_name: padinvasion
    hostname: cryptpad
    restart: always

    environment:
      - CPAD_MAIN_DOMAIN=cryptpad.mydomain.de
      - CPAD_SANDBOX_DOMAIN=sandbox.mydomain.de
      - CPAD_CONF=/cryptpad/config/config.js

    volumes:
      - /var/lib/cryptpad/data/blob:/cryptpad/blob
      - /var/lib/cryptpad/data/block:/cryptpad/block
      - /var/lib/cryptpad/customize:/cryptpad/customize
      - /var/lib/cryptpad/data/data:/cryptpad/data
      - /var/lib/cryptpad/data/files:/cryptpad/datastore
      - /var/lib/cryptpad/config.js:/cryptpad/config/config.js

    ports:
      - '3000:3000'
      - '3001:3001'
      - '3003:3003'

    
    ulimits:
      nofile:
        soft: 1000000
        hard: 1000000

Caddyfile (I guess the Strict-Transport-Security header should go as header_up in the reverse_proxy block. I will try this out later):

(cryptpadheaders) {
	header {
		Strict-Transport-Security "max-age=63072000; includeSubDomains" always
	}
}
cryptpad.mydomain.de, sandbox.mydomain.de {
	reverse_proxy 127.0.0.1:3000 {
		header_up Host {upstream_hostport}
		header_up Connection upgrade
	}
	import cryptpadheaders
}

config.js:

module.exports = {
    httpUnsafeOrigin: 'https://cryptpad.mydomain.de',
     httpSafeOrigin: 'https://sandbox.mydomain.de',
    httpAddress: '::',
    // websocketPort: 3003,
     maxWorkers: 6,
    //otpSessionExpiration: 7*24, // hours
    //enforceMFA: false
    adminKeys: [
        "[myadminkey]",
    ],
    // supportMailboxPublicKey: "",
    adminEmail: 'myadminmail',
    blockDailyCheck: false,
    defaultStorageLimit: 500 * 1024 * 1024,
    inactiveTime: false, // days
    archiveRetentionTime: 60,
    accountRetentionTime: false,
    disableIntegratedEviction: true,
    //maxUploadSize: 20 * 1024 * 1024,

    customLimits: {
        "[somekey]": {
            limit: 20 * 1024 * 1024 * 1024,
            plan: 'insider',
            note: 'admin'
        },
      }, 
    //premiumUploadSize: 100 * 1024 * 1024,
    filePath: './datastore/',
    archivePath: './data/archive',
    pinPath: './data/pins',
    taskPath: './data/tasks',
    blockPath: './block',
    blobPath: './blob',
    blobStagingPath: './data/blobstage',
    decreePath: './data/decrees',
    logPath: './data/logs',
    logToStdout: true,
    logLevel: 'info',
    logFeedback: false,
    verbose: false,
    installMethod: 'unspecified',
};

I also noticed that the Docker installation guide only covers installing it with a Dockerfile, not using the docker-compose.yaml. Would it be ok for me to update it (once I figured out the next two versions with Only-Office) explaining it using docker-compose?

a year later

Hi,
I know it's an old thread, but I am having a similar setup (but caddy as proxy is on a different machine than cryptpad).
The last suggestion works but I get disconnection errors on a regular basis. Also the setup of the SandBox-Part and Websocket are missing. Did you extend your Caddy-Config and get it work?

Thank you.

Best