Joplin Server and Nginx under subresource and HTTPS

Hi :wave:t2:

I'm trying to set up Joplin Server on my Raspberry Pi. Here some basic facts:

  • Joplin Server 2.7.4
  • Raspberry Pi 4, arm64/v8

This is my docker-compose.yml:

version: '3'
services:
    app:
        environment:
            - APP_BASE_URL=http://myRaspi:22300
            - APP_PORT=22300
            - POSTGRES_PASSWORD=reallySecret
            - POSTGRES_DATABASE=joplin
            - POSTGRES_USER=joplin
            - POSTGRES_PORT=5432
            - POSTGRES_HOST=db
            - DB_CLIENT=pg
        restart: unless-stopped
        image: florider89/joplin-server:latest
        ports:
            - "22300:22300"
    db:
        restart: unless-stopped
        image: postgres:13.1
        ports:
            - "5432:5432"
        volumes:
            - /home/myUser/Docker/joplin-data:/var/lib/postgresql/data
        environment:
            - POSTGRES_PASSWORD=reallySecret
            - POSTGRES_USER=joplin
            - POSTGRES_DB=joplin

I'm using Nginx as reverse proxy and I can successfully access Joplin server via http://myRaspi:22300. But I'd like to host it under https://myRaspi/joplinServer with a redirect to http://myRaspi:22300. Nginx is already configured to serve https://myRaspi.

So I've tried the following docker-compose.yml:

version: '3'
services:
    app:
        environment:
            - APP_BASE_URL=https://myRaspi/joplinServer
            - APP_PORT=443
            - POSTGRES_PASSWORD=reallySecret
            - POSTGRES_DATABASE=joplin
            - POSTGRES_USER=joplin
            - POSTGRES_PORT=5432
            - POSTGRES_HOST=db
            - DB_CLIENT=pg
        restart: unless-stopped
        image: florider89/joplin-server:latest
        ports:
            - "22300:443"
    db:
        restart: unless-stopped
        image: postgres:13.1
        ports:
            - "5432:5432"
        volumes:
            - /home/myUser/Docker/joplin-data:/var/lib/postgresql/data
        environment:
            - POSTGRES_PASSWORD=reallySecret
            - POSTGRES_USER=joplin
            - POSTGRES_DB=joplin

And the Nginx config looks like this:

server {
    listen 443 ssl;
    ssl_certificate /etc/ssl/certs/myRaspi.crt;
    ssl_certificate_key /etc/nginx/ssl/certificates/myRaspi.pem;

    location /joplinServer {
        proxy_pass         https://myRaspi:22300/joplinServer;
    }
}

But that gives me just Bad Gateway.

Can someone please help me figuring out how to make Joplin Server available via https://myRaspi/joplinServer?

Thank you!

This URL is the problem I guess...it should be http://myRaspi:22300.

Kind regards

That gives...
image

Ah, the APP_PORT and the ports: have to stay the same with and without reverse proxy (in each case 22300 and 22300:22300)...

Maybe take a look at my guide for Joplin Server:

1 Like

That gives Invalid origin: http://myRaspi:22300

First, in your .env only your url should be present:

APP_BASE_URL=https://myRaspi/joplinServer (without the port)

Second, you shouldn't tinker with the docker compose file, so you shouldn't edit the APP_BASE_URL value there, as it will be relayed by the .env file (thus, should simply be by default, - APP_BASE_URL=${APP_BASE_URL}).

Last, in your Nginx config, the proxy pass should look like this: http://127.0.0.1:22300

Also in Nginx, a few headers should be present, such as:
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;
proxy_pass_header Content-Type;

This should get you going as these are the working settings on a "production" server.

Now I have the following configuration:

  • /home/myUser/Docker/.env:
APP_BASE_URL=https://myRaspi/joplinServer
  • /home/myUser/Docker/docker-compose.yml:
version: '3'
services:
    app:
        environment:
            - APP_BASE_URL=${APP_BASE_URL}
            - APP_PORT=22300
            - POSTGRES_PASSWORD=reallySecret
            - POSTGRES_DATABASE=joplin
            - POSTGRES_USER=joplin
            - POSTGRES_PORT=5432
            - POSTGRES_HOST=db
            - DB_CLIENT=pg
        restart: unless-stopped
        image: florider89/joplin-server:latest
        ports:
            - "22300:22300"
    db:
        restart: unless-stopped
        image: postgres:13.1
        ports:
            - "5432:5432"
        volumes:
            - /home/myUser/Docker/joplin-data:/var/lib/postgresql/data
        environment:
            - POSTGRES_PASSWORD=reallySecret
            - POSTGRES_USER=joplin
            - POSTGRES_DB=joplin
  • Nginx config:
server {
    listen 443 ssl;
    ssl_certificate /etc/ssl/certs/myRaspi.crt;
    ssl_certificate_key /etc/nginx/ssl/certificates/myRaspi.pem;

    location /joplinServer {
        proxy_pass         http://127.0.0.1:22300;
        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;
        proxy_pass_header  Content-Type;
    }
}

This is how I start it:

cd /home/myUser/Docker
docker compose up -d

But I still get...
image

In this case, remove /joplinServer from the APP_BASE_URL, the rest remains the same.

On a side note, the proxy headers should be a "global" declaration but it is not relevant to you current problem.

Now I've set APP_BASE_URL=https://myRaspi in .env, still giving me the same error:
image

When clicking on Go to login page, an HTTP 404 at https://myRaspi/login occurs

Interesting..my latest idea was from this topic (last comment, same issue): Using basic Docker config leads to Path not found: joplin/login (and many other CSS/JS elements not found) ยท Issue #6548 ยท laurent22/joplin ยท GitHub

This is rather weird, as I've helped many users here set up their own servers so it would have to work with all these infos, but let me give you my own actual settings so it may give you ideas.

.env (the relevant part, other than this I have only the db password and the mailing module set up):
APP_BASE_URL=https://joplin.domain.com

docker-compose.yml: default, didn't change a thing here as everything comes from the environment file

Reverse proxy (Nginx)(only the relevant information from the config):

server {
listen 443 ssl http2;
server_name joplin.domain.com;

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;
proxy_pass_header Content-Type;

location / {
   proxy_redirect off;
   proxy_pass http://127.0.0.1:22300;
}

I believe the issue lies with your reverse proxy config, that's why I go into it this deep.

Could you please post your docker-compose.yml anyways?

Ah and one difference is that you're not running Joplin Server under a subresource, right?

Yes, that's the difference, I gave it a subdomain on my server.

I could post my docker-compose file if you insist, but it's literally the default one, didn't change a thing in it.

Edit:

The contents of the docker-compose.yml, though I honestly see no point in posting it, it is the default file:

version: '3'

services:
db:
image: postgres:13
volumes:
- ./data/postgres:/var/lib/postgresql/data
ports:
- "5432:5432"
restart: unless-stopped
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_DB=${POSTGRES_DATABASE}
app:
image: joplin/server:latest
depends_on:
- db
ports:
- "22300:22300"
restart: unless-stopped
env_file: .env
environment:
- APP_PORT=22300
- APP_BASE_URL=${APP_BASE_URL}
- DB_CLIENT=pg
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DATABASE=${POSTGRES_DATABASE}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PORT=${POSTGRES_PORT}
- POSTGRES_HOST=db

Thx anyways, just wanted to double-check.

Now I have the same settings as you, except the subresource. Maybe somebody could confirm whether this is even possible?
Any other option is possible as well - I'm running a Raspberry Pi 4 behind a FritzBox - so if creating a subdomain is an option (I'm not familiar to that), any hints would be appreciated

image

It looks like the proxy server is not just directing the request to http://127.0.0.1:22300 it is also appending joplinServer to the end, making the full request http://127.0.0.1:22300/joplinServer. Joplin Server has no such path so you get the error. Whether you can reverse proxy these requests in a manner that prevents this is beyond me!! I had a try and failed...

If your FritzBox does not allow you to create custom dns entries you could build a Pi-Hole and tell the FritzBox to use that for DNS lookups. You can then use the Pi-Hole GUI to use custom, non-internet domains / subdomains on your network.

If you use an .env file for the Joplin environment settings you do not need an environment section in the Joplin part of the docker-compose.yml file. The Postgres db environment variables are unlikely to change and so can stay in the compose file. Using an .env file means you can make changes to Joplin settings whilst leaving the main compose file well alone.

docker-compose.yml (for a sub-domain setup)

Not sure if the port 465:465 mapping is needed for setting up the server email but I did it and it worked.

Click to show
version: '3'
services:
    db:
        restart: unless-stopped
        image: postgres:13.4
        ports:
            - "5432:5432"
        volumes:
            - /home/myUser/Docker/joplin-data:/var/lib/postgresql/data
        environment:
            - POSTGRES_PASSWORD=pgpassword
            - POSTGRES_USER=pgusername
            - POSTGRES_DB=pgdbname
    app:
       restart: unless-stopped
       image: florider89/joplin-server:latest
       depends_on:
            - db
       ports:
            - "22300:22300"
            - "465:465"
       env_file: .env

.env (for a sub-domain setup)

This contains some Joplin environment variables you can play with if you want. The extra ones are mainly for setting up the Joplin server's email system but ACCOUNT_TYPES_ENABLED=1 would allow you to set users up with the equivalent default quotas / settings of basic and pro accounts. It's a while since I last "toggled" some of these so I can only assume that they still work. When it comes to the mailer security settings, search this forum for mailer_security for help, if needed.

Click to show
APP_NAME=myRaspi Joplin Server
APP_BASE_URL=https://joplin.example.com
APP_PORT=22300
POSTGRES_PASSWORD=pgpassword
POSTGRES_DATABASE=pgdbname
POSTGRES_USER=pgusername
POSTGRES_PORT=5432
POSTGRES_HOST=db
DB_CLIENT=pg
MAILER_ENABLED=1
MAILER_HOST=smtp.example.com
MAILER_PORT=465
MAILER_SECURITY=tls
MAILER_AUTH_USER=mail@sexample.com
MAILER_AUTH_PASSWORD=mail_account_password
MAILER_NOREPLY_NAME=JoplinServer
MAILER_NOREPLY_EMAIL=noreply@example.com
SIGNUP_ENABLED=0
TERMS_ENABLED=0
ACCOUNT_TYPES_ENABLED=0

Does Joplin Server have no possibility to say "Hey, you're running under this subresource?" I know this from ASP.NET Core, where I can say app.UsePathBase("/joplinServer");

I think that the problem lies with the nginx setup and not Joplin as what you are asking for is basically the Joplin Server base path environment variable. It's just that nginx adds to it.

Try this:

In your .env file set APP_BASE_URL=https://myRaspi/joplinServer as well as any other variables.

or forget the .env file and just use the docker-compose file.

version: '3'
services:
    db:
        restart: unless-stopped
        image: postgres:13.1
        ports:
            - "5432:5432"
        volumes:
            - /home/myUser/Docker/joplin-data:/var/lib/postgresql/data
        environment:
            - POSTGRES_PASSWORD=reallySecret
            - POSTGRES_USER=joplin
            - POSTGRES_DB=joplin
    app:
        environment:
            - APP_BASE_URL=https://myRaspi/joplinServer
            - APP_PORT=22300
            - POSTGRES_PASSWORD=reallySecret
            - POSTGRES_DATABASE=joplin
            - POSTGRES_USER=joplin
            - POSTGRES_PORT=5432
            - POSTGRES_HOST=db
            - DB_CLIENT=pg
        restart: unless-stopped
        image: florider89/joplin-server:latest
        depends_on:
            - db
        ports:
            - "22300:22300"

... and in your nginx server block section for the proxy_pass location add the rewrite instruction (as below):

    # Proxy headers
    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;

    location /joplinServer/ {
       proxy_redirect off;
       rewrite     ^/joplinServer/(.*)$ /$1 break;
       proxy_pass http://127.0.0.1:22300;
    }

The trailing slashes after joplinServer in the server block location section appear to be important.

When I do that on my test system if I type just the url without /joplinServer I get sent to the default nginx welcome page. However if I add /joplinServer I get sent to the server login page.

server_login

I will let you test if you can still sync with this server after all this abuse!!

2 Likes

You're the hero of the day :partying_face: that works perfectly, thank you so much!