Joplin server db issues during syncing

Operating system

Linux

Joplin version

3.4.1

Sync target

Joplin Server

What issue do you have?

Long story, some highlights:

  • deployed per the GitHub with docker-compose and basically no customization otherwise (Postgres DB, no storage driver)
  • on a modest VPS (~1 GB RAM)
  • accidentally uploaded maybe a dozen or two non-scaled images that are like 40MP, almost immediately started getting 504 gateway issues when trying to sync

took a number of actions already,

  • restored to a recent db backup, no change
  • figured out that the db was getting killed+restarted due to OOM; added a new swap file and reconfigured compose config to use it, verified that this issue is resolved, but 504 persists
  • changed some nginx settings for timeouts and buffer sizes --> now 504 is gone, instead getting:

[error] App: 154.27.160.58 KnexTimeoutError: Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?

  • added DB_POOL_SIZE=20 to the environment variables, and via psql ran REINDEX and VACUUM full; --> no change

since I'm on a DB version without the large files and took several steps to add margin, not clear why it's still failing; maybe some cache somewhere still being processed but I have not been able to locate it?

anyway, searching I stumbled on this, and decided that maybe running everything through the DB is not viable on my modest system:

I added the relevant env variables (STORAGE_DRIVER, STORAGE_DRIVER_FALLBACK) and restarted the containers, no issues --> I assume working

but that doesn't address the issue if it's db performance and all of the data is in the db still, so I tried to migrate per the GitHub; this fails because of duplicated part of the path, I guess the GitHub needs to be updated?

  • as follows:

/opt/joplin # docker exec -it joplin-app-1 node packages/server/dist/app.js storage import --connection 'Type=Filesystem; Path=/opt/joplin/storage'
node:internal/modules/cjs/loader:1143
throw err;
^
Error: Cannot find module '/home/joplin/packages/server/packages/server/dist/app.js'

  • correcting that path issue, it tries to run and fails, repeating the last line incessantly:

2025-08-24 03:53:50: ImportContentCommand: Importing to storage: { type: 2, path: '/opt/joplin/storage' }
2025-08-24 03:53:50: ImportContentCommand: Batch size: 1000
2025-08-24 03:53:50: ImportContentCommand: Max content size: 200000000
2025-08-24 03:53:50: ImportContentCommand: Processing items 0 / 16421
2025-08-24 03:53:50: [error] ImportContentCommand: [Error: EACCES: permission denied, mkdir '/opt/joplin'] {
errno: -13,
code: 'EACCES',
syscall: 'mkdir',
path: '/opt/joplin'
}

so here is where I am stuck. I will also point out one sentence from the above forum post that seems important but I don't see it reflected in the GitHub documentation:

You also need to add a docker volume ./data:/path/to/dir to persist the data on server.

any thoughts on where to go next? I'd really rather not nuke the existing db and start over, but it's starting to sound more and more attractive. but not sure how clients are going to handle that if there are conflicting local versions now... (sync has been broken for a couple weeks)

thanks!

ah, an important missing detail!

the local notes with the large images were deleted locally, and then the DB was rolled back. it’s not like the client is expected to be syncing the same large notes still, barring some cache somewhere.

After accumulating so many issues, I would start from scratch. Do you have a good JEX backup somewhere? Check How to fix synchronisation issues and start over

thanks, I take some solace in the fact that all of the issues would seem to logically come from the action I took (too many large files); but the persistence is troubling.

thanks for the link. I'll go ahead and make a backup of the offender client (my device which has the majority of the unique – not shared – content; there are 4 or so other clients out there...), wipe and try to sync again. I swear that I tried syncing another client that should have no knowledge of the offending files right after db restore and still failed, though, so not sure that there’s not something still on the server… anyway, if I can’t get any client to sync, then I guess a need a more drastic action than what this link covers. but I'll give it a try.

regardless, it does seem like getting the local storage driver set up will be beneficial for me long term, so I still want to make sure I'm getting that set up correctly. I guess the most likely the error I'm getting is that the app is trying to write the data inside the container and not on the host, which would make sense with permissions in that location (and also the negative effect that it would be lost at times, I assume? -- I'm a quite new to docker)

after some reading, I'm going to let docker manage the volume and not just bind directly to a host dir:

I need to verify the container path here yet, however I think something like this is what is needed...

services:
    joplin_app:
        volumes:
            - joplin_note_data:./data
volumes:
  joplin_note_data:

ok -- yea, logically the path for the storage driver is local.

sigh, some more adventures:

I created, inside the Joplin server container,

./note_data

which is in ~/packages/server by default; and adjusted the docker compose yaml accordingly.

restarted the containers (docker-compose --file Joplin-docker-compose.yml restart), and trying to migrate the db data to it succeeds. however I only checked volume status after with docker volumes ls and found no volume... for some reason it did not start and I just wrote out 1.2GB of data from the db into the Joplin app local filesystem.

docker exec -it joplin-app-1 node dist/app.js storage import --connection 'Type=Filesystem; Path=./note_data'

seems that docker-compose restart ... perhaps did not load the changes? because explicit docker-compose --file ... down / docker-compose --file ... up --> generates the error that I can't use a relative path.

so fixing that to FQPs,

services:
    db:
        image: postgres:16
        mem_limit: 0.8g        # hard memory limit
        memswap_limit: 3.8g     # allow container to use up to 3.8GB (0.8GB RAM + 3GB swap)
        volumes:
            - ./data/postgres:/var/lib/postgresql/data
        ports:
            - "***************"
        restart: unless-stopped
        environment:
            - POSTGRES_PASSWORD=*****************
            - POSTGRES_USER=joplin-server
            - POSTGRES_DB=joplindb
    app:
        image: joplin/server:latest
        volumes:
            - joplin_note_data:/home/joplin/packages/server/note_data
        depends_on:
            - db
        mem_limit: 0.8g        # hard memory limit
        mem_reservation: 0.4g # soft memory limit
        memswap_limit: 3.8g     # allow container to use up to 3.8GB (0.8GB RAM + 3GB swap)
        ports:
            - "********************"
        restart: unless-stopped
        environment:
            - APP_PORT=************
            - APP_BASE_URL=****************
            - DB_CLIENT=***************
            - POSTGRES_PASSWORD=****************
            - POSTGRES_DATABASE=joplindb
            - POSTGRES_USER=joplin-server
            - POSTGRES_PORT=****************
            - POSTGRES_HOST=db
            - DB_POOL_SIZE=20
            - STORAGE_DRIVER=Type=Filesystem; Path=/home/joplin/packages/server/note_data
            - STORAGE_DRIVER_FALLBACK=Type=Database; Mode=ReadAndWrite

volumes:
    joplin_note_data:

now I can docker-compose --file ... up -d successfully... and it starts a volume, except:

  • Joplin server is complaining of no permission to access it.
  • ls -lah within the container shows the location (/home/joplin/packages/server/note_data) has root:root ownership... despite me making this before as the joplin user.
  • taking DOWN the containers; commenting out the volume lines in the docker-compose YAML; and restarting... the directory is GONE including everything I dumped to it.

I do realize now that my database does write out to the host via bind (instead of named volumes). maybe I encountered this and edited permissions on the host machine sometime back when setting this up, I really have no recollection of doing so... and so maybe that will be the path here... but I am just flabbergasted that docker-compose fails so hard here, and all of the solutions I see seem quite hacky? e.g. this: How to mount a volume with docker-compose with owner www-data user of the container? - Stack Overflow
sorry, I realize this is getting more into docker issues and support than Joplin, but I hope its appropriate as it seems to be the recommended way to run Joplin-server and I think the example config on GitHub is a bit under-specified for newer dockers users like me.

and I guess I am back to restoring the DB from a backup before trying anything else.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.