Joplin is a popular open-source note-taking app loved by privacy-minded folks and productivity gurus. It’s easy to sync your notes across devices, but if you want to keep your data totally safe and in your hands, you can set up your own Joplin server.

Let’s walk through how to do this step by step. We’ll start by preparing your server and configuring it to suit your needs. Whether you want to boost security, save money, or make it unique to your needs, self-hosting Joplin is the way to go.

First step: installing Docker on your Raspberry Pi

We’ll start under the assumption you’ve already got your Raspberry Pi installed and running. I’m doing this on a Raspberry Pi 5 running Raspberry Pi OS (64-bit, release date October 22, 2024). First, you must update and upgrade your distribution with the latest packages.

  1. Open a Terminal session on your Raspberry Pi.
  2. Update the apt package manager to be sure its database is current:
    sudo apt update
  3. Next, upgrade any packages that haven’t already been upgraded:
    sudo apt upgrade -y

Next, you’ll need to install and configure Docker if you don’t already have it installed. Docker allows you to run apps and servers in sandboxed containers, so you don’t have to worry about different pieces of software conflicting with one another.

  1. First, download and install the latest Docker packages:
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  2. Make sure Docker is installed successfully by running this command, which will download a test image and run it in a container:
    sudo docker run hello-world
    When the container runs, it displays a confirmation message and then exits.
  3. Next, add your current user to the docker group to avoid having to use root privileges:
    sudo user mod -aG docker $USER
  4. Finally, exit your Terminal session and open a new one to refresh your user permissions.

We’ll install docker-compose to finish and make it easier to create new Docker containers.

  1. First, install the needed prerequisites for docker-compose.
    sudo apt install -y libffi-dev libssl-dev python3-dev python3-pip
  2. Now you can install docker-compose with this command:
    sudo pip3 install docker-compose
  3. If you get an error that the environment is externally managed, issue this command instead:
    sudo apt install docker-compose-plugin

Install a web server and self-signed certificate

Once Docker is installed, you’re almost ready to install your Joplin server. First, we must ensure it has a web server and an SSL certificate to keep it secure.

You might also want to set up your domain name and dynamic DNS to allow remote access to the Joplin server. These steps are beyond the scope of this article since setting up dynamic DNS varies widely from one router to the next. However, without this, you can only sync your notes when you’re on the same network as the Joplin server.

Let’s move on to setting up the web server you’ll use for your Joplin server.

  1. First, install the nginx web server:
    sudo apt install -y nginx
  2. To set up SSL, create your certificate authority (CA) private key. When asked for a passphrase, it’s a good idea to use one to prevent possible security breaches. Just use this command and follow the instructions as they appear:
    sudo openssl genrsa -aes256 -out /etc/ssl/private/local_ca.key 4096
  3. Next, you need to create a certificate. We’ll create a CA certificate valid for five years (1826 days) with the following command. When asked for a passphrase, use the one you created above in step 2.
    sudo openssl req -x509 -new -nodes -key /etc/ssl/private/local_ca.key -sha256 -days 1826 -out /etc/ssl/certs/local_ca.crt
    You’ll be asked to provide additional information, but you can skip any of the fields using the period (.).

After creating your CA and self-signed certificates, nginx will need its own certificate for the web server.

First, create a self-signed certificate for the nginx service:

sudo openssl req -new -nodes -out /etc/ssl/certs/nginx.csr -newkey rsa:4096 -keyout /etc/ssl/private/nginx.key -subj '/CN=Nginx Service'

The web server needs an extension file to configure certificate settings, such as hostname and IP address. Copy the following text into the Terminal, changing the values for DNS.1 and IP.1 to your Raspberry Pi’s hostname and IP address:

cat > nginx.ext

authorityKeyIdentifier=keyid,issuer

basicConstraints=CA:FALSE

keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment

subjectAltName = @alt_names

[alt_names]

DNS.1 = [Type Raspberry's hostname here]

IP.1 = [Type Raspberry's IP address here]

EOF

Verify the contents are correct using:

cat nginx.ext

Finally, sign the certificate for nginx with this command:

sudo openssl x509 -req -in /etc/ssl/certs/nginx.csr -CA /etc/ssl/certs/local_ca.crt -CAkey /etc/ssl/private/local_ca.key -CAcreateserial -out /etc/ssl/certs/nginx.crt -days 3650 -sha256 -extfile nginx.ext

Okay, we’re almost ready to install the Joplin server. Before we do that, however, we need to create a new nginx configuration for the Joplin server. Create a new configuration file using nano in your Terminal session:

sudo nano /etc/nginx/sites-enabled/joplin

Copy and paste the following information, making sure to edit server_name to match your configuration:

server {

listen 443 ssl http2;

server_name raspberrypi.local;

ssl_certificate /etc/ssl/certs/nginx.crt;

ssl_certificate_key /etc/ssl/private/nginx.key;

location /joplin/ {

proxy_redirect off;

proxy_pass http://127.0.0.1:22300;

rewrite ^/joplin/(.*)$ /$1 break;

proxy_set_header X-Forwarded-Host $host;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Forwarded-Proto $scheme;

}

}

Save and exit using Ctrl+X, [Y], and Enter/Return.

Finally, restart nginx to apply the new server configuration:

sudo systemctl restart nginx.service

Setting up your self-hosted Joplin server

With the preliminaries out of the way, it’s time to install and configure the Joplin server. Docker will do most of the work for us, following recipes in the Docker repositories. To get the ball rolling, you’ll need to create a new docker-compose.yml file. In the Terminal, issue this command:

nano docker-compose.yml

Next, copy and paste the text below into the file, then save the file and exit nano.

version: '3'

services:

db:

restart: unless-stopped

image: postgres:13.1

ports:

- "5432:5432"

volumes:

- /data/joplin-data:/var/lib/postgresql/data

environment:

- POSTGRES_PASSWORD=[Enter postgres password here]

- POSTGRES_USER=[Enter postgres username here]

- POSTGRES_DB=[Enter postgres db name here]

app:

environment:

- APP_BASE_URL=https://[raspberry hostname here]/joplin

- APP_PORT=22300

- POSTGRES_PASSWORD=[Enter postgres password here]

- POSTGRES_DATABASE=[Enter postgres db name here]

- POSTGRES_USER=[Enter postgres username here]

- POSTGRES_PORT=5432

- POSTGRES_HOST=db

- DB_CLIENT=pg

restart: unless-stopped

image: etechonomy/joplin-server:latest

ports:

- "127.0.0.1:22300:22300"

depends_on:

- db

Next, you’ll use the configuration file to download and install the required Docker images:

docker compose up -d

Finally, test the server is running by opening a new web browser window and navigating to:

https://[hostname].local/joplin

Replace hostname with the hostname you configured for the Raspberry Pi. You’ll likely get warnings about the certificate, but you can accept them by clicking Advanced -> Accept the Risk and Continue.

You should see the Joplin Server login page. The default username is admin@localhost, and the default password is admin. Be sure to change those immediately to maintain your security.

Connect your devices to the Joplin serverOnce the server config is complete, you can start synchronizing the Joplin app with your self-hosted server on your devices. You may need to import the security certificate you created to the devices you want to connect. Using email, SCP, or any other method, transfer a copy of the CA certificate found on your Raspberry Pi at /etc/ssl/certs/local_ca.crt to those devices.

Joplin Server is ready to go

That's about it. It's a lengthy process, but if you followed the instructions correctly, you should be good to go. Of course, your next step may be to make your Joplin server available online eventually. As previously mentioned, this will require registering your own domain name and using dynamic DNS to expose your Raspberry Pi Joplin server to the outside world, so be sure to fully secure your Pi before doing so.