Joplin Server: Sync Not Working — Fix

The Problem

Joplin desktop or mobile app won’t sync with your self-hosted Joplin Server. Common symptoms:

Completed: 25/02/2026 10:30
Last error: Error: ECONNREFUSED 127.0.0.1:22300
Sync failed: Could not connect to Joplin Server. Please check the Synchronisation options.

Or sync starts but items fail with 401/403 errors, notes don’t appear on other devices, or sync gets stuck showing “Synchronizing…” indefinitely.

The Cause

Joplin Server sync requires the desktop/mobile client to reach the server over HTTPS, authenticate successfully, and have matching sync target configuration. The most common failure points:

  1. Wrong sync target URL in the client — must include the full path and use the external URL
  2. Sync target type not set to “Joplin Server” — Joplin defaults to Dropbox, not self-hosted
  3. Reverse proxy not forwarding correctly — WebSocket or large request blocking
  4. PostgreSQL connection issues — server can’t reach its database
  5. SSL certificate problems — self-signed certs rejected by the client

The Fix

Method 1: Configure the Client Correctly (Most Common)

In the Joplin desktop app, go to Tools → Options → Synchronization and set:

SettingValue
Synchronization targetJoplin Server (not Joplin Cloud, not WebDAV)
Joplin Server URLhttps://joplin.example.com
Joplin Server emailYour user email (the one you created in the admin panel)
Joplin Server passwordYour user password

Common mistakes:

WrongRight
http://192.168.1.100:22300https://joplin.example.com (use the external URL)
Sync target: “Joplin Cloud”Sync target: “Joplin Server”
Sync target: “WebDAV”Sync target: “Joplin Server”
URL with trailing slash: https://joplin.example.com/https://joplin.example.com (no trailing slash)

After changing settings, click Check synchronization configuration to test the connection.

Method 2: Verify the Server Is Running

Check that Joplin Server is healthy:

# Check container status
docker compose ps

# Check server logs for errors
docker compose logs joplin-server --tail=50

# Test the API endpoint
curl -v https://joplin.example.com/api/ping
# Should return: {"status":"ok","message":"Joplin Server is running"}

If the container is restarting, check the logs for database connection errors (see Method 4).

Method 3: Fix Reverse Proxy Configuration

Joplin Server requires WebSocket support and handles large sync payloads. Your reverse proxy must allow both.

Nginx Proxy Manager: Ensure WebSocket support is enabled in the proxy host settings.

Nginx manual config:

server {
    listen 443 ssl;
    server_name joplin.example.com;

    client_max_body_size 200M;  # Required for large note attachments

    location / {
        proxy_pass http://127.0.0.1:22300;
        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;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Caddy:

joplin.example.com {
    reverse_proxy localhost:22300
}

Caddy handles WebSocket and large bodies automatically.

Key checks:

  • client_max_body_size (Nginx) must be large enough for attachments (200M recommended)
  • WebSocket upgrade headers must be forwarded
  • The proxy must not timeout long sync operations (set proxy_read_timeout 300s;)

Method 4: Fix PostgreSQL Connection

If the server logs show database errors:

Error: connect ECONNREFUSED 127.0.0.1:5432
error: password authentication failed for user "joplin"

Verify your database configuration:

services:
  joplin-server:
    image: joplin/server:3.5.2
    environment:
      APP_BASE_URL: https://joplin.example.com
      APP_PORT: 22300
      DB_CLIENT: pg
      POSTGRES_HOST: joplin-db        # Must match the PostgreSQL service name
      POSTGRES_PORT: 5432
      POSTGRES_DATABASE: joplin
      POSTGRES_USER: joplin
      POSTGRES_PASSWORD: strongpass    # Must match the database service
    depends_on:
      joplin-db:
        condition: service_healthy
    restart: unless-stopped

  joplin-db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: joplin
      POSTGRES_PASSWORD: strongpass
      POSTGRES_DB: joplin
    volumes:
      - joplin-db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U joplin"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

Ensure POSTGRES_HOST is the service name (joplin-db), not localhost.

Method 5: Fix SSL Certificate Issues

If the client shows SSL errors or sync fails with “certificate” in the error:

Self-signed certificates: The Joplin desktop app may reject self-signed certs. Go to Tools → Options → Synchronization → Advanced → Ignore TLS certificate errors and enable it (development only).

Let’s Encrypt: If using a reverse proxy with Let’s Encrypt, ensure the cert covers joplin.example.com. Test with:

curl -I https://joplin.example.com
# Check for: HTTP/2 200 and valid certificate

Internal network without SSL: If Joplin Server is only accessible on your LAN, use http:// in the sync URL and set APP_BASE_URL to match. However, sync over unencrypted HTTP is not recommended.

Method 6: Create a User Account

The default admin account is for server management, not syncing. Create a dedicated user:

  1. Open https://joplin.example.com in a browser
  2. Log in with the admin credentials (default: admin@localhost / admin)
  3. Go to Admin → Users → Add User
  4. Create a user with an email and password
  5. Use this email and password in the Joplin desktop app sync settings

If you’re trying to sync with the admin account and it fails, create a regular user instead.

Prevention

  • Always use the external HTTPS URL (not localhost:22300) in the client sync settings
  • Set the sync target to “Joplin Server” — not “Joplin Cloud” or “WebDAV”
  • Add a healthcheck on PostgreSQL so the server waits for the database
  • Set client_max_body_size to 200M+ in your reverse proxy
  • Test sync with Check synchronization configuration after any config change
  • Create a regular user for syncing — don’t use the admin account

Comments