Guide for Joplin-Server on Raspberry Pi

Hello,
thanks a lot for your effort setting up and maintaining this guide!

In my use-case I would like to run Joplin-Server exclusively locally, i.e. without being accessible from Internet.

Therefore, could you please describe relevant adjustments likely needed for steps 6. Certbot and subsequent sections?

Many thanks in advance!

If you'd like to have it running under e. g. 192.168.0.100:22300:
Skip step 1, 2, 5, 6, 7 and 10.
In step 8 you'd want to set the APP_BASE_URL to the local ip with the protocol in front and a leading :22300 (in this example http://192.168.0.100:22300).


If you'd like to have it running under e. g. 192.168.0.100/joplin:
Skip step 1, 2, 6 and 10.
In step 7 edit /etc/apache2/sites-enabled/000-default.conf instead of /etc/apache2/sites-enabled/000-default-le-ssl.conf (there will be no <VirtualHost *:443> block, but instead a <VirtualHost *:80> block.

In step 8 you would want to set the APP_BASE_URL to the local ip with the protocol in front and a leading /joplin (in this example http://192.168.0.100/joplin).


Remeber: The traffic gets routed without any encryption via plain http.

3 Likes

Thanks a lot - went for first variant and Joplin Server is up and running! :+1:

1 Like

For me docker is returning a:

#
# Fatal error in , line 0
# unreachable code
#
#
#
#FailureMessage Object: 0x75afd7a8```

Anyone got any ideas on this?

Please provide more information about your system:

  • Post your docker-compose file
  • Post output of uname -a
  • Post output of lsb_release -a

Hint: Use this template to hide long code blocks so the thread doesn't get too bloated

[details="Summary"]
This text will be hidden
[/details]

Thanks for the prompt response - here's what you requested

docker-compose

version: '3'
services:
db:
restart: unless-stopped
image: postgres:13.1
ports:
- "5432:5432"
volumes:
- /services/joplin-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=joplin
- POSTGRES_USER=joplin
- POSTGRES_DB=joplin
app:
environment:
- APP_BASE_URL=<https URL the forum won't let me post>/joplin
- APP_PORT=22300
- POSTGRES_PASSWORD=joplin
- POSTGRES_DATABASE=joplin
- POSTGRES_USER=joplin
- POSTGRES_PORT=5432
- POSTGRES_HOST=db
- DB_CLIENT=pg
restart: unless-stopped
image: etechonomy/joplin-server:latest
ports:
- "22300:22300"
depends_on:
- db

uname -a

Linux raspberrypi 5.10.103-v7+ #1529 SMP Tue Mar 8 12:21:37 GMT 2022 armv7l GNU/Linux

lsb_release -a

No LSB modules are available.
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 10 (buster)
Release: 10
Codename: buster

Also getting joplin_app_1 exited with code 133 if that helps

I can't really see a problem there. After a quick online search, the problem could be caused by Raspbian 10 / Debian 10 / Debian Buster. My advice would be: If you don't have a ton of other features running on the Raspberry Pi, upgrade it to Bullseye (use the newest image available) and start the guide from scratch.

Unfortunately I don't have a Raspberry Pi with Debian 10 running currently, so I can't test it.

@MrKanister Thanks for your tutorial, however I seem to fail at some point :frowning:

I needed to change all http-urls to h2tp, I am not allowed to post links.

I want to host joplin locally on my raspi4 and expose via nginx proxy and let's ecrypt certificate.
Joplin should be available on this domain
h2tps://subdomain.domain.tld:1234

Network setup will be like this
Router Port 1234➡2345 nginx listening➡proxy to joplin port 22300

I was able to get almost everything up and running. But opening h2tps://subdomain.domain.tld:1234/login will give me a bare html page with no css images etc. loaded.

sample h2tps://subdomain.domain.tld:1234/login
bare html page (

All urls in html sourcecode lead to http-url, no https and missing outside port 1234. e.g.
h2tp://subdomain.domain.tld/images/icons/server/icon-180.png

whereas this url severs the image perfectly:
h2tps://subdomain.domain.tld:1234/images/icons/server/icon-180.png

  • So it appears joplin is hardcoding the url by itself unable to handle outside port 1234 or https proxing, what did I configure wrong?
  • Do I have to rewrite all urls in nginx?
  • Does Joplin require outside port in APP_BASE_URL?
  • Can Joplin even handle different ports?
docker-compose

version: '3.5'
volumes:
joplin-db:
joplin-data:
joplin-nginx:
joplin-nginxlogs:
letsencrypt:
external: true

services:
db:
restart: unless-stopped
container_name: joplin-db
image: postgres:latest
ports:
- "5432:5432"
volumes:
- joplin-db:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=SECRET
- POSTGRES_USER=joplin
- POSTGRES_DB=joplin
app:
container_name: joplin-core
environment:
- APP_BASE_URL=h2tp://subdomain.domain.tld
- APP_PORT=22300
- POSTGRES_PASSWORD=SECRET
- POSTGRES_DATABASE=joplin
- POSTGRES_USER=joplin
- POSTGRES_PORT=5432
- POSTGRES_HOST=db
- DB_CLIENT=pg
- MAILER_ENABLED=1
- MAILER_HOST=SECRET
- MAILER_PORT=587
- MAILER_SECURITY=starttls
- MAILER_AUTH_USER=SECRET
- MAILER_AUTH_PASSWORD=SECRET
- MAILER_NOREPLY_NAME=SECRET
- MAILER_NOREPLY_EMAIL=SECRET
restart: unless-stopped
image: etechonomy/joplin-server:latest
ports:
- "22300:22300"
depends_on:
- db

web:
    image: nginx:1.24.0
    container_name: joplin-nginx
    restart: always
    ports:
      - "2345:2345"
    links:
      - app
    volumes:
      - joplin-nginx:/etc/nginx
      - letsencrypt:/etc/letsencrypt:ro
      - joplin-nginxlogs:/var/logs
nginx-config

server {
listen 2345 ssl http2;
server_name subdomain.domain.tld;

        ssl_certificate /etc/letsencrypt/live/SECRET.pem;
        ssl_certificate_key /etc/letsencrypt/live/SECRET.pem;

        location / {
            proxy_pass h2tp://joplin-core:22300;
            proxy_buffering off;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            }
    }

Phew, very specific use case!

Indeed this often is an indicator for an incorrect APP_BASE_URL. I'd try to add the outside port to it.

Yes, I think so, see this post: Guide for Joplin-Server on Raspberry Pi - #42 by MrKanister.

I don't think so, see the link above. You could possibly verify this by adding the port to the APP_BASE_URL and checking in the developer tools of your browser where the network requests are being sent to.

I think your desired behaviour should be possible, but I can't tell you exactly whether and where there is currently an error.

(Be aware, that certbot needs port 80 (and maybe 443) open on the pi for it's challenges if you are using it for the certificate on the pi.)

I am using this setup for almost all my docker containers and they all work fine. E.g. nextcloud, influxdb, unifi, grafana..

I just verified, adding the external port does not work :frowning:

  • APP_BASE_URL=h2tp://subdomain.domain.tld:1234

It seems the port is now actually part of the base url and does not match the passed url in http-header:

h2tp://subdomain.domain.tld:1234 <> h2tps://subdomain.domain.tld

Opening h2tps://subdomain.domain.tld:1234 will lead to:

Invalid origin: h2tps://subdomain.domain.tld

Since this message is send as plain-text there is no url, link, image or similar that is loaded after said message.

Thanks for the note regarding let's encrypt. I am handling certbot in another container that has port 80 forwarded, that works just fine :slight_smile:

@MrKanister Thanks for the sparring, I figured it out! :smiley:

All I needed is to trick joplin into getting the correct url passed in the forwarding header from nginx.
Nginx will now forward to port 22300 with a header containing 1234 as url.

nginx config:

proxy_set_header Host $host:1234;

joplin base url

APP_BASE_URL=h2tp://subdomain.domain.tld:1234

Network setup will be like this
Router Port 1234➡2345 nginx listening➡proxy to joplin port 22300

:white_check_mark:Working configuration

docker-compose

version: '3.5'
volumes:
joplin-db:
joplin-data:
joplin-nginx:
joplin-nginxlogs:
letsencrypt:
external: true

services:
db:
restart: unless-stopped
container_name: joplin-db
image: postgres:latest
ports:
- "5432:5432"
volumes:
- joplin-db:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=SECRET
- POSTGRES_USER=joplin
- POSTGRES_DB=joplin
app:
container_name: joplin-core
environment:
- APP_BASE_URL=h2tp://subdomain.domain.tld:1234
- APP_PORT=22300
- POSTGRES_PASSWORD=SECRET
- POSTGRES_DATABASE=joplin
- POSTGRES_USER=joplin
- POSTGRES_PORT=5432
- POSTGRES_HOST=db
- DB_CLIENT=pg
- MAILER_ENABLED=1
- MAILER_HOST=SECRET
- MAILER_PORT=587
- MAILER_SECURITY=starttls
- MAILER_AUTH_USER=SECRET
- MAILER_AUTH_PASSWORD=SECRET
- MAILER_NOREPLY_NAME=SECRET
- MAILER_NOREPLY_EMAIL=SECRET
restart: unless-stopped
image: etechonomy/joplin-server:latest
ports:
- "22300:22300"
depends_on:
- db

web:
    image: nginx:1.24.0
    container_name: joplin-nginx
    restart: always
    ports:
      - "2345:2345"
    links:
      - app
    volumes:
      - joplin-nginx:/etc/nginx
      - letsencrypt:/etc/letsencrypt:ro
      - joplin-nginxlogs:/var/logs
nginx-config

server {
listen 2345 ssl http2;
server_name subdomain.domain.tld;

        ssl_certificate /etc/letsencrypt/live/SECRET.pem;
        ssl_certificate_key /etc/letsencrypt/live/SECRET.pem;

        location / {
            proxy_pass http://joplin-core:22300;
            proxy_buffering off;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header Host $host:1234;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Real-IP $remote_addr;
            }
    }
1 Like

Hi there,

Sorry to be so late to the party.

When following the initial post, and running:

sudo docker compose up -d

I'm told that the version is obsolete.

Any thoughts?

thanks

chris

Which version is obsolete? Please post the output you get as a code block (like this: ``` output ```)

I believe it says that "version" is obsolete.

The docker-compose file no longer requires the line version: '3'. You can ignore it or just delete the line.

GitHub - Version top-level element (obsolete)

1 Like

Awesome.

Okay, that hurdle cleared, onto the next:

my docker-compose.yaml looks like this:

services:
db:
restart: unless-stopped
image: postgres:latest
ports:
- "5432:5432"
volumes:
- /data/joplin-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=xxxx
- POSTGRES_USER=joplin
- POSTGRES_DB=joplin
app:
environment:
- APP_BASE_URL=https://xxxxxxx/joplin
- APP_PORT=22300
- POSTGRES_PASSWORD=xxxxx
- POSTGRES_DATABASE=joplin
- POSTGRES_USER=joplin
- POSTGRES_PORT=5432
- POSTGRES_HOST=db
- DB_CLIENT=pg
restart: unless-stopped
image: etechonomy/joplin-server:latest
ports:
- "22300:22300"
depends_on:
- db

This is what I get when I run sudo docker compose up -d

pi@raspberrypi:~ $ sudo docker compose up -d
WARN[0000] The "LhqkfzeR" variable is not set. Defaulting to a blank string.
WARN[0000] The "tv" variable is not set. Defaulting to a blank string.
WARN[0000] The "LhqkfzeR" variable is not set. Defaulting to a blank string.
WARN[0000] The "tv" variable is not set. Defaulting to a blank string.
[+] Running 0/2
⠧ db Pulling 0.6s
⠧ app Pulling 0.6s
no matching manifest for linux/arm/v8 in the manifest list entries

And this takes mere moments, not a long while.

Thanks

sorry for the formatting.

This suggests to me that docker is looking for externally stored environment variables but you have not obviously specified any in your compose file. It's a long shot but is your postgres password something like ${LhqkfzeR}${tv} ???

Also in the error it says arm. Are you trying to install Joplin Server on 32-bit RasPiOS? Joplin Server is a 64-bit application and needs a 64-bit OS to download / run the linux/arm64/v8 image.

Says here it's Arm 64 bit

:thinking: