Hi all,
We just finished our deployment of CryptPad using the official Docker method (no, we don't want to use Docker, but it's required right now). Unfortunately, after getting NGINX and CryptPad deployed, there's something amiss when a user attempts to register. The browser will show the following:

So, digging into configs, I still cannot see why this would be happening. Our setup is:
- NFTables on the host permitting inbound traffic on TCP 80 and 443, filtering on SYN flag for initial connection.
- NGINX reverse proxy on a Docker container with a custom bridge network and static IP, ports 80 and 443 exposed to the host.
- The official Cryptpad Docker image behind the reverse proxy on the same custom bridge network and a static IP.
All ingress traffic comes over TCP 443 and the RP maps to TCP 3000 and 3003 respectively. The configs we have (with domains redacted):
Nginx.conf
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /config/nginx/resolver.conf;
server_tokens off;
client_max_body_size 0;
sendfile on;
tcp_nopush on;
gzip_vary on;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
http2 on;
http3 off;
quic_retry off;
access_log /config/log/nginx/access.log;
client_body_temp_path /tmp/nginx 1 2;
proxy_temp_path /tmp/nginx-proxy;
fastcgi_temp_path /tmp/nginx-fastcgi;
uwsgi_temp_path /tmp/nginx-uwsgi;
scgi_temp_path /tmp/nginx-scgi;
proxy_cache_path /tmp/nginx-proxy-cache keys_zone=lsio-proxy:10m;
fastcgi_cache_path /tmp/nginx-fcgi-cache keys_zone=lsio-fcgi:10m;
scgi_cache_path /tmp/nginx-scgi-cache keys_zone=lsio-scgi:10m;
uwsgi_cache_path /tmp/nginx-uwsgi-cache keys_zone=lsio-uwsgi:10m;
include /etc/nginx/http.d/.conf;
include /config/nginx/site-confs/.conf;
}
CryptPad block
server {
listen 80;
server_name DomainA DomainB;
access_log /dev/null;
error_log /dev/null emerg;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
http2 on;
server_name DomainA DomainB;
ssl_certificate /config/keys/cert.crt;
ssl_certificate_key /config/keys/cert.key;
ssl_dhparam /config/nginx/dhparams.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
location / {
proxy_pass http://DomainA:443;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 150m;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
location ^~ /cryptpad_websocket {
proxy_pass http://DomainB:3003;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
}
config.js
module.exports = {
httpUnsafeOrigin: 'https://DomainA',
httpSafeOrigin: 'https://DomainB',
httpAddress: '192.168.0.3',
httpPort: 443,
websocketPort: 3003,
otpSessionExpiration: 1*12,
enforceMFA: true,
logIP: true,
adminKeys: [],
inactiveTime: 90,
archiveRetentionTime: 15,
accountRetentionTime: 365,
disableIntegratedEviction: false,
maxUploadSize: 20 * 1024 * 1024,
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: false,
logLevel: 'info',
logFeedback: false,
verbose: false,
installMethod: 'unspecified',
};`
application_config.js
(() => {
const factory = (AppConfig) => {
AppConfig.loginsalt = '[REDACTED]';
AppConfig.minimumPasswordLength = 24
AppConfig.registeredOnlyTypes = AppConfig.availablePadTypes;
AppConfig.disableAnonymousPadCreation = true;
AppConfig.disableAnonymousStore = true;
AppConfig.defaultDarkTheme = true;
return AppConfig;
};
if (typeof(module) !== 'undefined' && module.exports) {
module.exports = factory(
require('../www/common/application_config_internal.js')
);
} else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) {
define(['/common/application_config_internal.js'], factory);
}
})();
If anyone has seen this before or sees a misconfiguration on my part, I would greatly appreciate some feedback. Thanks!