Skip to main content

Self-Host Memos: Lightweight Notes and Microblog 2026

·OSSAlt Team
memosnotesself-hostingdockerproductivitymicroblog2026

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 #tags inline — 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

FeatureMemosApple NotesNotionStandard Notes
PriceFree (self-host)Free (iCloud)$8/mo (Plus)$90/yr
Data ownershipFullAppleNotionE2E encrypted
MarkdownYesNoPartialYes
Feed/timelineYesNoNoNo
TagsInline #tagsFoldersPagesTags
APIRESTNoRESTNo
Multi-userYesVia iCloud sharingYesNo
OfflinePWANativeLimitedNative
Self-hostedYesNoNoYes

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)

![Images can be uploaded or pasted](image.png)

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

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

LevelWho can see
PrivateOnly you
ProtectedLogged-in users on your instance
PublicAnyone with the URL

Set visibility per memo:

  • Default: Private
  • Click the 🔒 icon → switch to Protected or Public

Share a memo

  1. Click Share
  2. Copy the direct link: https://memos.yourdomain.com/m/abc123
  3. 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

  1. Shortcuts → New → Ask for Input (text)
  2. 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"}
  3. Show Result: "Saved!"
  4. 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

RoleCapabilities
Host (Admin)Full access, manage users, system settings
AdminCreate/edit/delete own memos, view protected memos
UserCreate/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.

Comments