How to Self-Host Joplin Server with Docker
What Is Joplin Server?
Joplin Server is the official sync backend for Joplin, an open-source note-taking application. Joplin itself is a desktop and mobile app (Windows, macOS, Linux, iOS, Android) that supports Markdown, end-to-end encryption, notebooks, tags, and to-do lists. Joplin Server replaces cloud sync services (Dropbox, OneDrive, Nextcloud) with a self-hosted sync target that gives you complete control over your data.
The server handles synchronization between Joplin clients. You write and read notes in the Joplin desktop/mobile apps, and the server keeps everything in sync. The server also provides a web interface for basic note viewing and sharing.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 1 GB of RAM minimum
- 5 GB of free disk space (scales with note and attachment volume)
- A domain name (required for HTTPS sync)
Docker Compose Configuration
Create a docker-compose.yml file:
services:
joplin-server:
image: joplin/server:3.5.2
ports:
- "22300:22300"
environment:
APP_PORT: 22300
APP_BASE_URL: ${APP_BASE_URL}
DB_CLIENT: pg
POSTGRES_HOST: postgres
POSTGRES_PORT: 5432
POSTGRES_DATABASE: joplin
POSTGRES_USER: joplin
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
MAILER_ENABLED: 0
# Uncomment to enable email notifications:
# MAILER_ENABLED: 1
# MAILER_HOST: smtp.example.com
# MAILER_PORT: 587
# MAILER_SECURITY: starttls
# MAILER_AUTH_USER: ${SMTP_USER}
# MAILER_AUTH_PASSWORD: ${SMTP_PASSWORD}
# MAILER_NOREPLY_EMAIL: [email protected]
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: joplin
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: joplin
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U joplin -d joplin"]
interval: 10s
timeout: 3s
retries: 3
restart: unless-stopped
volumes:
postgres-data:
Create a .env file alongside:
# The full URL where Joplin Server is accessible (no trailing slash)
APP_BASE_URL=https://joplin.yourdomain.com
# PostgreSQL password — use a strong random password
POSTGRES_PASSWORD=change_me_strong_password
Start the stack:
docker compose up -d
Initial Setup
- Navigate to your Joplin Server URL (e.g.,
https://joplin.yourdomain.com) - Log in with the default admin credentials:
- Email:
admin@localhost - Password:
admin
- Email:
- Change the admin password immediately — go to Admin → Users → admin → Change Password
- Create user accounts for each person who will sync notes
- Each user gets their own email and password for connecting Joplin clients
Connecting Joplin Desktop/Mobile
- Open Joplin on your device
- Go to Tools → Options → Synchronization (desktop) or Settings → Sync (mobile)
- Set Synchronization target to “Joplin Server”
- Enter:
- Joplin Server URL:
https://joplin.yourdomain.com - Email: Your user email
- Password: Your user password
- Joplin Server URL:
- Click “Check synchronization configuration” to verify
- Click “Synchronize” — your notes sync to the server
Configuration
End-to-End Encryption
Joplin supports end-to-end encryption (E2EE) configured in the Joplin desktop/mobile clients (not on the server). When enabled, notes are encrypted before leaving your device — the server stores encrypted blobs and cannot read your content.
Enable in Joplin client: Tools → Options → Encryption → Enable encryption
Set a master password. All connected devices must use the same master password to decrypt notes.
User Management
The admin panel at /admin provides:
- Create/delete users
- Set storage quotas per user (e.g., 1 GB, 10 GB, unlimited)
- Monitor user storage usage
- View sync activity
File Size Limits
By default, Joplin Server limits upload size. Set MAX_ASSET_SIZE in bytes to increase:
environment:
MAX_ASSET_SIZE: 209715200 # 200 MB
Advanced Configuration (Optional)
Email Configuration
Enable email for user registration confirmations and password resets:
environment:
MAILER_ENABLED: 1
MAILER_HOST: smtp.example.com
MAILER_PORT: 587
MAILER_SECURITY: starttls
MAILER_AUTH_USER: your_smtp_user
MAILER_AUTH_PASSWORD: your_smtp_password
MAILER_NOREPLY_EMAIL: [email protected]
Storage Backend
By default, Joplin Server stores note content and attachments in PostgreSQL. For very large deployments, you can configure S3-compatible storage. Check the Joplin Server documentation for S3 configuration details.
Reverse Proxy
Set up a reverse proxy to access Joplin Server over HTTPS. Point your proxy to port 22300. HTTPS is strongly recommended — sync credentials are sent with every request.
Ensure the APP_BASE_URL matches the external URL exactly.
For detailed setup: Reverse Proxy Setup
Backup
Critical data to back up:
- PostgreSQL database:
docker compose exec postgres pg_dump -U joplin joplin > joplin_backup.sql— this contains all notes and attachments - Environment file: Your
.envwith the database password and URL
Restore: cat joplin_backup.sql | docker compose exec -T postgres psql -U joplin joplin
Note: If you use Joplin’s E2EE, the database backup contains encrypted data. You need the master password to decrypt after restore.
For a complete backup strategy: Backup Strategy
Troubleshooting
Sync fails with “403 Forbidden”
Symptom: Joplin client shows 403 when trying to sync.
Fix: Verify the email and password are correct. Check that the user account exists and is enabled in the admin panel. Ensure APP_BASE_URL matches the URL you’re using in the client exactly (including https://).
”Connection refused” when syncing
Symptom: Client can’t connect to the server.
Fix: Check that Joplin Server is running: docker compose ps. Verify port 22300 is accessible. If behind a reverse proxy, ensure the proxy is forwarding correctly to port 22300.
Large sync takes very long or times out
Symptom: Initial sync with many notes (1000+) is extremely slow or fails.
Fix: Increase MAX_TIME_DRIFT if clients have clock differences. For the initial sync, use a wired connection. Consider increasing PostgreSQL’s work_mem for large databases. The first sync is always the slowest.
Default admin login doesn’t work
Symptom: admin@localhost / admin is rejected.
Fix: This only works on the very first login. If you’ve already initialized the server and forgot the password, you’ll need to reset it via the database: docker compose exec postgres psql -U joplin -d joplin -c "UPDATE users SET password = '' WHERE email = 'admin@localhost';" then set a new password through the web UI.
E2EE “Master password required” on new device
Symptom: After setting up a new device, notes appear but are encrypted. Fix: Go to Tools → Options → Encryption and enter the master password. All devices must use the same master password to decrypt E2EE notes.
Resource Requirements
- RAM: ~150 MB idle, 300-500 MB under active sync load
- CPU: Low — spikes during bulk sync operations
- Disk: ~100 MB for the application, plus your note data (attachments can add up quickly)
Verdict
Joplin Server is the best self-hosted sync solution if you’re already using or planning to use Joplin as your note-taking app. The client apps are solid (especially the desktop app), Markdown support is excellent, and E2EE provides genuine privacy.
The main limitation is that Joplin Server is primarily a sync backend — the web interface is basic. If you want a full web-based note experience, Outline or BookStack are better. If you want a personal knowledge base with hierarchical notes and relation maps, Trilium offers more organizational power. But for syncing Markdown notes across devices with end-to-end encryption, Joplin Server is the right tool.
Related
Get self-hosting tips in your inbox
New guides, comparisons, and setup tutorials — delivered weekly. No spam.