Abstract
“CryptPad is a collaborative office suite that is end-to-end encrypted and open-source.” - CryptPad’s website
I’ve been hosting a CryptPad instance for a few years, but have been using it a lot more recently for things like notes and calendaring as it is easier than keeping everything synced between devices. It operates a lot like Office 365 or Google Drive’s office suite, however, CryptPad is self-hosted, open source, and puts privacy first.
Setting up a CryptPad instance is not particularly difficult depending on what your security concerns are. For example, my original CryptPad instance was self-hosted on my LAN inside of a FreeBSD jail. The concern for security and was less than if my instance would have been public, so, I just got it working rather than configuring it to production quality. However, for a public instance, there is a lot more tweaking involved to make sure the server itself is secure and has as few holes as possible for attackers. In this post I will be going over my experience with both an “insecure” setup and a “production” setup. The insecure setup is not recommended, but might make the most sense for someone only concerned about having access to it on their LAN rather than across the Internet. For a public CryptPad instance available on the Internet, please do your research. CryptPad has a very good guide on setting up a public instance for CryptPad, before trying anything in this blog post, start there. This post is more so recounting some issues that I had (that were likely self-imposed).
Insecure CryptPad setup
My “insecure” CryptPad instance is running inside of a FreeBSD jail, so all of the commands will assume FreeBSD. However, this should not be terribly difficult to translate into Linux (s/pkg/apt/g and s//usr/local/${dir}/\/${dir}/g should suffice in most cases). When setting up any new server, making sure everything is up-to-date is highly important. After that, install Nginx, node20, npm-node20, and git.
# Run the following as root
pkg update && pkg upgrade
pkg install -y git nginx node20 npm-node20
Note: Nginx is the recommended web server for use with CryptPad. Other web servers will work, but the documentation will references Nginx configs which might make getting the setup complete easier
Then download CryptPad and install dependencies.
git clone https://github.com/cryptpad/cryptpad.git cryptpad && cd cryptpad
npm install
npm run install:components
From here, copy the example config file by running
cp config/config.example.js config/config.js
then run
node server
to start CryptPad. While CryptPad will
technically run like this, it will not actually be useful until
modifying config/config.js
. Within the config file, there
are some variables that must be changed for CryptPad to actually be
accessible from other machines on the network. The first set of
variables that must be changed are: httpUnsafeOrigin
and
httpSafeOrigin
. What these variables do is not particularly
important in this section, however, will become much more important
during the “Production” section of this post. For now, just set the
variable to whatever domain name that the instance will be used from
(i.g. localdocs.internal). The next configuration item that must be
changed is httpAddress
. By default it only listens on
localhost and should be changed to whatever the IP address of the server
is going to be. Alternatively, it can listen on all ports, but that
creates much more attack surface on the server than necessary. All of
the other defaults should be fine to get CryptPad working; though it is
worth reading through the different configuration options available.
Next we configure the web server to be able to proxy the correct ports. Nginx has some configuration examples in the default config file, but it is just as easy to add another server block to do the proxy. The following example assumes that the domain name being used for the CryptPad instance is ‘localdocs.internal’, the IP address of the server is 192.168.1.100, and that the ‘httpPort’ in CryptPad’s config file has remained unchanged.
server {
listen: 80;
server_name localdocs.internal;
location / {
proxy_pass http://192.168.1.100:3000;
}
# If this is not set, then CryptPad will not load properly,
# and the application will be unusable
location = /cryptpad_websocket {
proxy_pass http://localhost:3000;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
}
}
Then just make sure that Nginx is enabled by adding
nginx_enable="YES"
to /etc/rc.conf, then start by running
service nginx start
as root. From there, run
node server
in the cryptpad directory, then attempt to
visit the page at localdocs.internal. Assuming it loads, the last thing
to do is to make CryptPad run as a daemon. This can be done by using the
daemon
utility in FreeBSD, or by using the example
rc.d file to create a service.
Production CryptPad setup
The production instance is similar to the insecure instance, however, you will also need to have a domain with an SSL certificate. I used certbot for this as it is quick and easy while also costing nothing (Go EFF!). Also for this, we must have two domains (at least subdomains) to help prevent XSS attacks on the CryptPad instance. This section of the blog post will be in more general terms as there is quite a bit of information that will vary from instance to instance, plus the example Nginx config does quite a good job of documenting what everything does. The first thing to do is to make sure that each of the domain names is registered so that they point to the server, and thus can get an SSL cert.
# All commands must be run as root
# Install certbot
pkg install py-certbot-nginx
# Then get the certificates for the domains
certbot --nginx
# Alternatively you can just get the certs,
# but it will be more work
certbot certonly --nginx
The next step is to copy the example Nginx config file into the
current Nginx config file so it can be modified to fit the instance we
are trying to set up. While there are likely 100 ways to do this in
FreeBSD, the way that made sense to me was to fetch the file,
then as root run
cat example.nginx.conf >> /usr/local/etc/nginx/nginx.conf
.
This command will copy the example.nginx.conf file to the end of the
current nginx config file. It can then be opened in ${EDITOR} and the
server block for CryptPad can be moved to a more suitable location and
the editing process can begin. Again, this file will vary from person to
person a bit, and there will be a bit of trial and error to get the
configuration correct. The ‘main_domain’ is the domain (or subdomain)
that the site will be accessed from. The ‘sandbox_domain’ is a
secondairy domain that is used strictly as a security measure against
XSS attacks. There will also be some SSL items that will have to be
commented out as the example file has some SSL configuration that should
have been handled already if you installed your certs with it.
Once nginx is configured, enabled, and started, we can then start
working with CryptPad itself to get it configured and working. First, as
in the other section of this post, copy the
config.example.js
to config.js
in the
config
folder in CryptPad. Then open config.js
in ${EDITOR} and begin configuring it for your instance. Change
httpUnsafeOrigin
to the same as the
main_domain
in the Nginx config file, change
httpSafeOrigin
to the same as the
sandbox_domain
in the Nginx config file. Most everything
else can be left as default, however, it is worth a look at the rest of
the config file as there are some other useful configuration items in
there. From there, run node server
and attempt to access
the page. If it loads and you are able to login and access the drive or
another app, the configuration works. Now just use the rc.d
script to make CryptPad a service and manage it as such.
More Documentation
CryptPad is a very well documented project with a lot of helpful resources to get started. Because of that, if you are interested in setting up your own public instance, I recommend starting there rather than this documentation. These pages are good for starting out with CryptPad and asking for help.