Loosing access after every update

Operating system

Linux

Joplin version

3.5.2

What issue do you have?

I use joplin on Docker, with a tailscale sidecar. Yesterday, I upgraded tailscale image and also did a docker pull on joplin (using :latest), as I saw there was an update (version 3.6.1) but :latest seems to always point to version 3.5.2.

This morning, on start, I can't login to joplin (neither admin nor users) , I have "invalid user or password" error message.

Logs only show :

pm2 launched in no-daemon mode (you can add DEBUG="*" env variable to get more messages)
2026-04-26T10:53:21: PM2 log: Launching in no daemon mode
2026-04-26T10:53:21: PM2 log: [PM2][Module] Starting NPM module pm2-logrotate
2026-04-26T10:53:21: PM2 log: [PM2][WARN] Applications pm2-logrotate not running, starting...
2026-04-26T10:53:21: PM2 error: (node:63) [DEP0176] DeprecationWarning: fs.R_OK is deprecated, use fs.constants.R_OK instead
(Use node --trace-deprecation ... to show where the warning was created)
2026-04-26T10:53:21: PM2 log: App [pm2-logrotate:0] starting in -fork mode-
2026-04-26T10:53:21: PM2 log: App [pm2-logrotate:0] online
2026-04-26T10:53:21: PM2 log: [PM2] App [pm2-logrotate] launched (1 instances)
2026-04-26T10:53:21: PM2 log: [PM2] Starting /home/joplin/packages/server/dist/app.js in fork_mode (1 instance)
2026-04-26T10:53:21: PM2 log: App [app:1] starting in -fork mode-
2026-04-26T10:53:21: PM2 log: App [app:1] online
2026-04-26T10:53:21: PM2 log: [PM2] Done.
2026-04-26T10:53:21: PM2 log: ┌────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 1 │ app │ default │ 3.5.2 │ fork │ 85 │ 0s │ 0 │ online │ 0% │ 19.0mb │ joplin │ disabled │
└────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
2026-04-26T10:53:21: PM2 log: Module
2026-04-26T10:53:21: PM2 log: ┌────┬──────────────────────────────┬───────────────┬──────────┬──────────┬──────┬──────────┬──────────┬──────────┐
│ id │ module │ version │ pid │ status │ ↺ │ cpu │ mem │ user │
├────┼──────────────────────────────┼───────────────┼──────────┼──────────┼──────┼──────────┼──────────┼──────────┤
│ 0 │ pm2-logrotate │ 3.0.0 │ 74 │ online │ 0 │ 200% │ 47.6mb │ joplin │
└────┴──────────────────────────────┴───────────────┴──────────┴──────────┴──────┴──────────┴──────────┴──────────┘
2026-04-26T10:53:21: PM2 log: [--no-daemon] Continue to stream logs
2026-04-26T10:53:21: PM2 log: [--no-daemon] Exit on target PM2 exit pid=63
10:53:23 1|app | 2026-04-26 10:53:23: [error] db: update knex_migrations set name = '20250404091200_user_auth_code.js' where name = '202504040912000_user_auth_code.js' - SQLITE_ERROR: no such table: knex_migrations {
10:53:23 1|app | "$1": "20250404091200_user_auth_code.js",
10:53:23 1|app | "$2": "202504040912000_user_auth_code.js"
10:53:23 1|app | }

yaml :

tailscale:
container_name: tailscale-${SERVICE} # Name for local container management
image: tailscale/tailscale:latest # Image to be used
hostname: ${SERVICE} # Name used within your Tailscale environment
environment:
- TS_AUTHKEY=${TS_AUTHKEY}
- TS_STATE_DIR=/var/lib/tailscale
- TS_SERVE_CONFIG=/config/serve.json # Tailscale Serve configuration to expose the web interface on your local Tailnet - remove this line if not required
- TS_USERSPACE=false
- TS_ENABLE_HEALTH_CHECK=true # Enable healthcheck endpoint: "/healthz"
- TS_LOCAL_ADDR_PORT=127.0.0.1:41234 # The : for the healthz endpoint
- TS_ACCEPT_DNS=true # Uncomment when using MagicDNS
- TS_AUTH_ONCE=true
volumes:
- ./config:/config # Config folder used to store Tailscale files - you may need to change the path
- ./ts/state:/var/lib/tailscale # Tailscale requirement - you may need to change the path
- ./serve.json:/config/serve.json
devices:
- /dev/net/tun:/dev/net/tun # Network configuration for Tailscale to work
cap_add:
- net_admin # Tailscale requirement
ports:
- "22300:22300"
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:41234/healthz"] # Check Tailscale has a Tailnet IP and is operational
interval: 1m # How often to perform the check
timeout: 10s # Time to wait for the check to succeed
retries: 3 # Number of retries before marking as unhealthy
start_period: 10s # Time to wait before starting health checks
restart: always

joplin:
image: joplin/server:latest
container_name: joplin
network_mode: service:tailscale
restart: always
environment:
# Set Backend ENV Variables Here
APP_PORT: 22300
PUID: 1000
PGID: 1000
TZ: Europe/Paris
MAX_TIME_DRIFT: 0
APP_BASE_URL: https://joplin.tailxxx.ts.net
# Database Settings
DB_CLIENT: postgres
POSTGRES_USER: xxx
POSTGRES_PASSWORD: xxx
POSTGRES_DATABASE: joplin
POSTGRES_PORT: 5432
POSTGRES_HOST: postgres
DB_AUTO_MIGRATION: true
MAILER_ENABLED: 0
LOG_LEVEL: warn
depends_on:
postgres:
condition: service_healthy
tailscale:
condition: service_healthy

postgres:
container_name: postgres-joplin
image: postgres:17
restart: always
volumes:
- joplin-pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: xxx
POSTGRES_USER: xxx
POSTGRES_DB: joplin
healthcheck:
test: ["CMD", "pg_isready"]
interval: 30s
timeout: 20s
retries: 3

volumes:
joplin-pgdata:

I already had this problem once when doing tests, but I thought I made an error, there were no data in joplin, so I deleted all and restarted. This time, I have some date, I prefer not to delete all ...

Thanks

Update : I tried to login with default password (admin) and get access to joplin server. But, everything was lost, no more users, no more data sync.

It seems like my database was dropped.

Still looking for advice :slight_smile:

I stopped pointing to latest months ago after random updates kept screwing my joplin server. I hardcode a version and manually update it once a month or so. This way I control when the risky update happens and choose a calm time, so I have some spare time in case it goes wrong.

It once happened right in a middle of a work day and screwed it all, that is when I made this strategic change.

Ftr I cannot remember any screw up since I made this change.

I am also curious to know why you are using tailscale sidecar. Personally I use tailscale too and use the static permanent IP it provides. No dns needed.

I might be wrong, but from your logs i think your Postgres data may still be there.

log says:

SQLITE_ERROR: no such table: knex_migrations

so Joplin seems to be starting with SQLite, not Postgres.

In your compose file you have:

DB_CLIENT: postgres

but Joplin Server expects:

DB_CLIENT: pg

If the value is not pg, it can fall back to SQLite, which would explain why admin / admin works again and why it looks like a fresh empty server.

Before deleting anything, i’d stop Joplin and check whether the Postgres DB still has data. If you’re comfortable running a read-only psql check, something like this should show the counts:

docker compose exec postgres psql -U <your_postgres_user> -d joplin -c "select count(*) from users; select count(*) from items;"

If those counts are not empty, change DB_CLIENT: postgres to DB_CLIENT: pg and start Joplin again.

Once it’s back, it may be worth pinning the server image version instead of using latest.

Hello,

I suppose you're running tailscale on your host, and not in docker ? I'm running docker on my nas, which doesn't have a native tailscale client. So, I have to run a sidecar for each application I want to access outside of house.

Advantage is that I get a SSL certificate for every application (not sure if you can do it while running tailscale on host ?). But I agree it's more configuration, some overhead in CPU/RAM and sometimes a pain to configure

Thanks ... I don't know where I read DB_CLIENT=postgres :frowning: I update the configuration (already restart and resync the clients, but it's not really a problem)