Self-Host Memos: Lightweight Notes and Microblog 2026
TL;DR
Memos (MIT, ~33K GitHub stars, Go) is a privacy-first, lightweight note-taking app that feels like a personal Twitter feed. Jot down thoughts, code snippets, links, and ideas in Markdown — everything is timestamped and appears in a scrollable feed. Tags for organization, search for retrieval, REST API for automation. Standard Notes charges $90/year for premium; Apple Notes locks you into iCloud. Memos runs on your server with full data ownership.
Key Takeaways
- Memos: MIT, ~33K stars, Go — fast, lightweight notes with a feed-like UI
- Markdown: Full Markdown support with code blocks, links, images, and checklists
- Tags: Organize with
#tagsinline — no folders, no hierarchy, just tags - Timeline feed: Scrollable chronological feed like a personal microblog
- REST API: Full CRUD API for integrations — Telegram bot, iOS Shortcuts, CLI
- Multi-user: Invite others, share memos publicly, or keep everything private
- Tiny footprint: ~30MB RAM, SQLite — runs on the smallest server
Memos vs Apple Notes vs Notion vs Standard Notes
| Feature | Memos | Apple Notes | Notion | Standard Notes |
|---|---|---|---|---|
| Price | Free (self-host) | Free (iCloud) | $8/mo (Plus) | $90/yr |
| Data ownership | Full | Apple | Notion | E2E encrypted |
| Markdown | Yes | No | Partial | Yes |
| Feed/timeline | Yes | No | No | No |
| Tags | Inline #tags | Folders | Pages | Tags |
| API | REST | No | REST | No |
| Multi-user | Yes | Via iCloud sharing | Yes | No |
| Offline | PWA | Native | Limited | Native |
| Self-hosted | Yes | No | No | Yes |
Part 1: Docker Setup
# docker-compose.yml
services:
memos:
image: neosmemo/memos:stable
container_name: memos
restart: unless-stopped
ports:
- "5230:5230"
volumes:
- memos_data:/var/opt/memos
environment:
# Memos uses SQLite by default — zero config needed
# Optional: use PostgreSQL instead:
# MEMOS_DRIVER: postgres
# MEMOS_DSN: "postgresql://memos:password@db:5432/memos?sslmode=disable"
MEMOS_MODE: prod
volumes:
memos_data:
docker compose up -d
Visit http://your-server:5230 → create your admin account.
Part 2: HTTPS with Caddy
memos.yourdomain.com {
reverse_proxy localhost:5230
}
Part 3: Writing Memos
Quick capture
The text area at the top of the feed is always ready. Type a thought and hit Save:
Just discovered that Docker Compose v2.27 supports
`include` for composing multiple files natively.
No more `-f file1.yml -f file2.yml`!
#docker #til
Markdown features
# Headers
**Bold** and *italic*
- Bullet lists
- [x] Checklists
- [ ] Todo items
`inline code` and code blocks:
\`\`\`python
print("Hello from Memos!")
\`\`\`
> Blockquotes for excerpts
[Links](https://example.com)

Tags
Just type #tag anywhere in your memo — Memos automatically indexes it:
Great article on #kubernetes autoscaling.
Key takeaway: use VPA for #databases, HPA for #web-apps.
Tags appear in the sidebar for filtering.
Pinned memos
Pin important memos to the top of your feed:
- Click the ⋯ menu → Pin
- Pinned memos always appear first
Part 4: Organization
Tag sidebar
All tags appear in the left sidebar. Click a tag to filter your feed.
Nested tags work with /:
#work/project-a
#work/project-b
#personal/reading
#personal/ideas
Search
Full-text search across all memos:
kubernetes — keyword search
#docker — filter by tag
from:2026-01-01 — date filter
has:link — memos containing links
has:code — memos with code blocks
Filters
Save common filters for quick access:
- All memos — everything
- Tags — filter by specific tag
- Date range — this week, this month, custom
Part 5: Sharing and Visibility
Visibility levels
| Level | Who can see |
|---|---|
| Private | Only you |
| Protected | Logged-in users on your instance |
| Public | Anyone with the URL |
Set visibility per memo:
- Default: Private
- Click the 🔒 icon → switch to Protected or Public
Share a memo
- Click ⋯ → Share
- Copy the direct link:
https://memos.yourdomain.com/m/abc123 - Public memos are accessible without login
RSS feed
Public memos are available as an RSS feed:
https://memos.yourdomain.com/u/yourname/rss.xml
Subscribe from any RSS reader to follow someone's public notes.
Part 6: REST API
# Get your access token:
# Settings → Access Tokens → Create
TOKEN="your-access-token"
BASE="https://memos.yourdomain.com"
# Create a memo:
curl -X POST "$BASE/api/v1/memos" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "Automated memo from a script! #automation",
"visibility": "PRIVATE"
}'
# List memos:
curl "$BASE/api/v1/memos" \
-H "Authorization: Bearer $TOKEN" | jq '.memos[].content'
# Search memos:
curl "$BASE/api/v1/memos?filter=content.contains(\"kubernetes\")" \
-H "Authorization: Bearer $TOKEN"
# Delete a memo:
curl -X DELETE "$BASE/api/v1/memos/MEMO_NAME" \
-H "Authorization: Bearer $TOKEN"
Part 7: Integrations
Telegram bot
Capture memos from Telegram:
#!/usr/bin/env python3
# telegram-to-memos.py
import os
import requests
from telegram import Update
from telegram.ext import ApplicationBuilder, MessageHandler, filters
MEMOS_URL = "https://memos.yourdomain.com"
MEMOS_TOKEN = os.environ["MEMOS_TOKEN"]
TELEGRAM_TOKEN = os.environ["TELEGRAM_TOKEN"]
async def save_memo(update: Update, context):
text = update.message.text
requests.post(
f"{MEMOS_URL}/api/v1/memos",
headers={"Authorization": f"Bearer {MEMOS_TOKEN}"},
json={"content": text, "visibility": "PRIVATE"}
)
await update.message.reply_text("✅ Saved to Memos!")
app = ApplicationBuilder().token(TELEGRAM_TOKEN).build()
app.add_handler(MessageHandler(filters.TEXT, save_memo))
app.run_polling()
iOS Shortcuts
- Shortcuts → New → Ask for Input (text)
- Get Contents of URL:
- URL:
https://memos.yourdomain.com/api/v1/memos - Method: POST
- Headers:
Authorization: Bearer YOUR_TOKEN - Body:
{"content": "Shortcut Input", "visibility": "PRIVATE"}
- URL:
- Show Result: "Saved!"
- Add to Home Screen or Share Sheet
CLI quick-capture
# Add to ~/.bashrc or ~/.zshrc:
memo() {
curl -s -X POST "https://memos.yourdomain.com/api/v1/memos" \
-H "Authorization: Bearer $MEMOS_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"content\": \"$*\", \"visibility\": \"PRIVATE\"}" > /dev/null
echo "✅ Saved"
}
# Usage:
memo "Just found a great article on #rust error handling"
memo "TODO: update the CI pipeline #work"
Part 8: Multi-User Setup
Create additional users
Settings → Members → + Add Member:
Username: alice
Role: User / Admin
Roles
| Role | Capabilities |
|---|---|
| Host (Admin) | Full access, manage users, system settings |
| Admin | Create/edit/delete own memos, view protected memos |
| User | Create/edit/delete own memos, view protected memos |
Maintenance
# Update:
docker compose pull
docker compose up -d
# Backup (SQLite):
docker cp memos:/var/opt/memos/memos_prod.db \
memos-backup-$(date +%Y%m%d).db
# Or full data directory (includes uploaded files):
tar -czf memos-data-$(date +%Y%m%d).tar.gz \
$(docker volume inspect memos_memos_data --format '{{.Mountpoint}}')
# Logs:
docker compose logs -f memos
See all open source productivity tools at OSSAlt.com/categories/productivity.