On this page
Introduction
Self‑hosting a markdown‑based note‑taking app has become a staple for developers, sysadmins, and homelab hobbyists. The three projects that dominate the conversation today are Memos, Joplin, and Outline. Each claims to be lightweight, secure, and easy to run on a low‑cost VPS. In this post we’ll:
- Compare the three on features, performance, and security.
- Show a practical Docker‑Compose deployment that fits into a $5/month VPS (1 vCPU, 1 GB RAM, 25 GB SSD).
- Add TLS with Let’s Encrypt, and set up automated daily backups.
By the end you’ll know which tool matches your workflow and how to get it running in under an hour.
Quick Feature Overview
| Feature | Memos | Joplin | Outline |
|---|---|---|---|
| Primary use‑case | Quick, searchable memos & snippets | Full‑featured note‑taking with notebooks, tags, and attachments | Team‑oriented knowledge base with hierarchical pages |
| Markdown support | ✅ Full CommonMark + extensions | ✅ Full CommonMark + GFM + LaTeX | ✅ Full CommonMark + custom blocks |
| Rich media | Images, code blocks, tables | Images, PDFs, audio, video, web clippings | Images, PDFs, embed videos |
| Authentication | Email/password, OAuth (Google, GitHub) | Email/password, OAuth, local SQLite auth | Email/password, SSO (OAuth, SAML), LDAP |
| Search | Full‑text (SQLite/FTS5) | Full‑text (SQLite/FTS5) | Full‑text (PostgreSQL tsearch) |
| API | RESTful JSON, WebSocket for live updates | WebDAV + REST API (experimental) | GraphQL API |
| Export | JSON, Markdown, HTML | JEX (JSON), MD, PDF, HTML | Markdown, HTML, PDF |
| Multi‑user | Yes (via OAuth) | Yes (via server mode) | Yes (built‑in team management) |
| Docker image size | ~75 MB | ~150 MB | ~120 MB |
| License | AGPL‑3.0 | MIT | Apache‑2.0 |
Bottom line: Memos shines for personal, fast‑capture use; Joplin is the most feature‑rich for power users; Outline adds collaboration and hierarchical organization.
Detailed Comparison
1. Feature Set
Memos (self hosted)
- Speedy capture – a single‑page UI that feels like a web‑based sticky note board.
- Tagging & pinning – quick filters without nesting.
- Live preview – markdown renders instantly as you type.
- OAuth – Google, GitHub, and Microsoft providers out of the box.
Joplin (self hosted)
- Notebook hierarchy – unlimited nesting, perfect for project‑based organization.
- End‑to‑end encryption – optional client‑side encryption before data hits the server.
- Web Clipper – browser extension to save articles directly to Joplin.
- Rich attachment handling – audio recordings, PDFs, and even encrypted files.
Outline (self hosted)
- Page tree – documents can be nested arbitrarily, ideal for internal wikis.
- Team permissions – granular role‑based access (owner, editor, viewer).
- Built‑in search – full‑text with ranking, plus filters for tags and authors.
- Integrations – Slack notifications, Mattermost, and custom webhooks.
2. Performance & Resource Footprint
All three run comfortably on a $5 VPS, but there are nuances:
| Metric | Memos | Joplin | Outline |
|---|---|---|---|
| RAM usage (idle) | ~120 MB | ~250 MB | ~200 MB |
| CPU spikes (search) | Low (SQLite FTS5) | Low‑moderate (SQLite) | Moderate (PostgreSQL) |
| Disk I/O | Light (single SQLite file) | Moderate (SQLite + attachments) | Higher (PostgreSQL WAL) |
| Scaling | Works well up to a few hundred users | Handles thousands with proper DB tuning | Designed for teams; PostgreSQL scales better than SQLite |
If you plan to host more than 200 active users, Outline’s PostgreSQL backend gives you headroom, while Memos stays the most lightweight.
3. Security Considerations
| Aspect | Memos | Joplin | Outline |
|---|---|---|---|
| Transport security | TLS via reverse proxy (recommended) | Same | Same |
| Data at rest | SQLite (optional file encryption) | Optional client‑side encryption (AES‑256) | PostgreSQL with pgcrypto (optional) |
| Auth mechanisms | Email + OAuth2 | Email + OAuth2 + LDAP (via server) | Email + OAuth2 + SAML + LDAP |
| Vulnerability track record | Small community, quick patches (last CVE 2023‑xxxx) | Larger community, active security audits | Enterprise‑grade, regular updates |
| Backup strategy | Simple file copy of SQLite DB | Export JEX + file copy | pg_dump + media folder |
All three rely on TLS termination at a reverse proxy (Caddy or Nginx). The biggest difference is Joplin’s optional end‑to‑end encryption, which is a strong advantage if you store sensitive data locally.
Who Should Use Which?
| Profile | Recommended App | Why |
|---|---|---|
| Solo developer who wants a fast “brain‑dump” tool | Memos | Minimal UI, low RAM, easy OAuth login |
| Power user who needs notebooks, tags, and encryption | Joplin | Rich feature set, encryption, Web Clipper |
| Small team (3‑20 people) needing a shared knowledge base | Outline | Hierarchical pages, role‑based permissions, Slack integration |
When Not to Use These Apps
- Memos – not ideal if you need deep notebook hierarchy or built‑in collaboration features.
- Joplin – avoid if you plan to run many simultaneous users on a tiny VPS; SQLite can become a bottleneck.
- Outline – overkill for a single user, and the PostgreSQL requirement adds complexity on a $5 VPS.
Docker‑Compose Deployment on a $5 VPS
Below is a single‑file Docker‑Compose setup that can spin up any of the three apps, add Let’s Encrypt TLS with Caddy, and schedule daily backups using a lightweight restic container.
Prerequisites
- A VPS with Docker ≥ 20.10 and Docker‑Compose ≥ 2.0.
- A domain name pointing to the VPS IP (e.g.,
notes.example.com). - Port 80 and 443 open in the firewall.
Directory Layout
~/notes/
├─ docker-compose.yml
├─ data/
│ ├─ memos/
│ ├─ joplin/
│ └─ outline/
└─ backup/
└─ restic/
Create the base folder and sub‑folders:
mkdir -p ~/notes/data/{memos,joplin,outline} ~/notes/backup/restic
cd ~/notes
1. Docker‑Compose File
# docker-compose.yml
version: "3.8"
services:
# -------------------------------------------------
# 1️⃣ Memos (swap this for joplin or outline)
# -------------------------------------------------
memos:
image: ghcr.io/usememos/memos:latest
container_name: memos
restart: unless-stopped
environment:
- MEMOS_PORT=5230 # internal port
- MEMOS_MODE=prod
volumes:
- ./data/memos:/var/opt/memos
expose:
- "5230"
# -------------------------------------------------
# 2️⃣ Caddy (TLS termination & reverse proxy)
# -------------------------------------------------
caddy:
image: caddy:2-alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
# -------------------------------------------------
# 3️⃣ Restic backup (daily)
# -------------------------------------------------
backup:
image: restic/restic:latest
container_name: backup
restart: unless-stopped
environment:
- RESTIC_REPOSITORY=/backup_repo
- RESTIC_PASSWORD=SuperSecretBackupPass
volumes:
- ./backup/restic:/backup_repo
- ./data/memos:/data_to_backup:ro # change to joplin/outline as needed
entrypoint: ["/bin/sh","-c"]
command: |
while true; do
restic backup /data_to_backup && \
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 && \
sleep 86400;
done
volumes:
caddy_data:
caddy_config:
Switching apps:
- To run Joplin, replace the
memosservice with the Joplin server image (joplin/server:latest) and adjust the volume path to./data/joplin. - For Outline, replace with
outlinewiki/outline:latestand expose port 3000.
2. Caddyfile (TLS + Reverse Proxy)
Create Caddyfile in the same folder:
notes.example.com {
encode gzip
reverse_proxy memos:5230
tls {
# Caddy obtains Let’s Encrypt cert automatically
# No extra config needed for a public domain
}
}
If you use Joplin (port 22300) or Outline (port 3000), change the reverse_proxy line accordingly.
3. Launch the Stack
docker compose up -d
Caddy will request a Let’s Encrypt certificate for notes.example.com. Verify everything works by visiting https://notes.example.com.
4. Verify Resource Usage
On a $5 VPS, you can check memory with:
docker stats --no-stream
Typical idle numbers:
- Memos – ~130 MB RAM, 0.1 CPU
- Joplin – ~260 MB RAM, 0.2 CPU
- Outline – ~210 MB RAM, 0.2 CPU
Leave a margin of ~300 MB for the OS and backup container.
5. Automated Backups Explained
The backup service runs an infinite loop that:
- Takes a snapshot of the selected data folder (
/data_to_backup). - Prunes old snapshots (
--keep-daily 7,--keep-weekly 4,--keep-monthly 6). - Sleeps for 24 hours.
You can restore a backup with:
docker run --rm -v $(pwd)/backup/restic:/backup_repo \
-e RESTIC_REPOSITORY=/backup_repo \
-e RESTIC_PASSWORD=SuperSecretBackupPass \
restic/restic restore latest --target /tmp/restore
Copy the restored files back into the appropriate data directory if needed.
Pros & Cons Summary
| App | Pros | Cons |
|---|---|---|
| Memos | • Tiny footprint, fast startup <br>• Simple UI for quick capture <br>• OAuth out of the box | • No deep notebook hierarchy <br>• Limited collaboration features |
| Joplin | • Rich notebook & tag system <br>• Optional end‑to‑end encryption <br>• Web Clipper for browsers | • Higher RAM usage <br>• SQLite may need tuning for many users |
| Outline | • Team‑oriented with roles <br>• Hierarchical pages work as a wiki <br>• PostgreSQL scales better | • More complex setup (PostgreSQL) <br>• Overkill for solo use |
Frequently Asked Questions
1. Can I run two of these apps on the same VPS?
Yes. Duplicate the service block in docker-compose.yml, give each a unique container name, expose a different internal port, and add a separate host entry in the Caddyfile (e.g., memos.example.com and outline.example.com).
2. Does Memos support end‑to‑end encryption?
Memos does not provide built‑in client‑side encryption. If you need that level of secrecy, Joplin’s optional E2EE is the better choice.
3. How do I migrate notes from Joplin to Memos?
Export your Joplin notes as Markdown (Joplin → File → Export → MD) and import them into Memos via the “Import” button in the UI, or copy the files into the data/memos folder and let Memos index them.
4. Can I use a custom domain with Let’s Encrypt on a VPS behind NAT?
Yes, as long as the domain’s DNS A record points to the VPS public IP and ports 80/443 are reachable. Caddy handles the ACME challenge automatically.
5. What’s the best backup destination for the restic container?
Mount a persistent volume on the VPS for local backups, or attach a remote S3‑compatible bucket (e.g., Wasabi, DigitalOcean Spaces) by adding RESTIC_REPOSITORY=s3:s3.amazonaws.com/your-bucket and providing the required credentials as environment variables.
Conclusion
Choosing the right self‑hosted markdown note‑taking app hinges on your workflow:
- Memos for lightning‑fast personal memos.
- Joplin for a full‑featured, encrypted notebook.
- Outline for a collaborative knowledge base.
All three run comfortably on a $5 VPS with the Docker‑Compose recipe above. The stack gives you TLS encryption, automated daily backups, and a clean separation of concerns via Caddy and Restic.
Give one of them a spin, tweak the resources to your traffic, and enjoy a private, ad‑free note‑taking environment. For more homelab guides, check out the rest of the articles on mahbuburriad.com.