# Memos self-hosting: what the docker run line mounts, and what the calendar tags cost you

> A read of usememos/memos: the four flags in the quick start docker command, the switch from v-prefixed tags to YY.MM calendar tags, the upgrade step required for anything older than v0.31.0, and the dependency surface a Go module file reveals behind the quick-capture pitch.

**usememos/memos** — Open-source, self-hosted note-taking tool built for quick capture. Markdown-native, lightweight, and fully yours.

- Repository: https://github.com/usememos/memos
- Website: https://usememos.com
- Stars: 63,423 · Forks: 4,796
- Language: Go
- License: MIT
- Published: 2026-08-04 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/usememos-memos

## Four docker flags, and the ones the quick start leaves out

The entire quick start is a single detached container with four arguments, and each one carries a decision. `--name memos` gives you a stable handle for later stops and logs. `-p 5230:5230` publishes the service on the host. `-v ~/.memos:/var/opt/memos` is the one that decides whether your notes survive: state lives in a directory under your home directory on the host, so deleting the container does not delete the notes, while running the same image without the mount keeps the notes inside the container layer where removing it discards them. The image tag is `neosmemo/memos:stable`.

```bash
docker run -d \
  --name memos \
  -p 5230:5230 \
  -v ~/.memos:/var/opt/memos \
  neosmemo/memos:stable
```

What this command does not contain is the rest of running a service: no reverse proxy, no TLS, no certificate, no environment variables, no database flags, no backup step. The host port is also published without a host address, which is the widest form of that mapping. None of that is presented as a feature gap so much as a scope decision, since the quick start says other install options are in the deployment guide, but a reader who copies this line onto a public host has decided their own exposure.

## Calendar tags and v-prefixed tags both appear, so pin with care

The quick start describes a version scheme and the releases list uses a different one, and anyone automating against the repository has to notice that. Releases are said to use `YY.MM`, with optional point releases such as `26.09.1` and release candidates such as `26.09-rc.1`, and calendar release tags carry no `v` prefix. The three most recent releases on the repository are named the other way: v0.31.0 on 2026-09-19, v0.31.0-rc.2 on 2026-09-15, and v0.31.0-rc.1 on 2026-08-30. A script that assumes one scheme will fail to resolve a tag under the other, and the fix is to check the actual tag name on the releases page rather than deriving it.

The Docker tags have their own motion. `stable` follows stable releases and `canary` follows development builds, so `neosmemo/memos:stable` is a moving pointer, not a fixed artifact. The same command run twice a month apart can land on different builds, which is the reason to pin a digest if you care about repeatability. The release candidates in that list are also a signal: two of the three most recent tags are prereleases of the same version, so the final tag came after a short candidate window.

## Upgrading from before v0.31.0 is a two step operation

The quick start spends a sentence on upgrades and it is the one sentence worth reading twice. If you are on a release from before v0.31.0, the instruction is to run v0.31.0 first and confirm it succeeded, and only then continue. Older versions are covered by the upgrade requirements kept in store/migration/README.md, which is the file to open before touching a live instance. So a jump from an old tag to a new one is not a single pull, it is an intermediate hop through a specific version, and the failure mode of skipping it is a migration that the project has already flagged as unsafe.

The store/ directory at the top of the repository is where that migration logic lives, next to the other backend code. A reader planning an upgrade should treat the store/migration file as part of the deploy procedure rather than as developer documentation, because the readme points at it from the operator's section. Nothing in the quick start describes what a failed intermediate migration looks like, so the safe move is to copy the mounted directory before starting rather than to read the error afterwards.

## The go.mod is much wider than a capture-first note app

The module file is where the real shape of the project shows. It declares `go 1.27.0`, so building from source needs that toolchain, and then requires drivers for three database families: the MySQL driver, `lib/pq` for Postgres, and `modernc.org/sqlite`. It also requires the AWS SDK v2 including the S3 service client, plus `gofakes3`, a fake S3 implementation that the project uses somewhere in its test setup. The HTTP side is `labstack/echo/v5`, with `cobra` and `viper` for the command line and configuration, and the transport stack includes gRPC, the gRPC gateway, protobuf, and connectrpc.

The part that surprises readers is the tail of the list: a Model Context Protocol Go SDK, an OpenAI Go client at v3, and a Google genai client are all direct requirements. Those are the pieces that make the project larger than a note logger, and they are exactly the parts a self-hoster should look at before deciding which of them an instance actually turns on. The readme's four reasons for choosing Memos say nothing about them, so the dependency list is the honest place to answer the question.

## No title, no folder, no template, and nothing named for export

The capture story is a refusal of structure: write in Markdown, attach media, and save without choosing a title, folder, or template. The organisation story that replaces it names four things, the timeline, search, tags, and pins. A pin is a flag on an entry, not a container, and a tag is a flat label, so the hierarchy that a folder tree would give you does not exist here. That is a deliberate trade for fast capture, and it has a cost: the longer the timeline runs, the more you lean on search and tags to find anything, and a note with no title has to be recognised by its first line.

The other absence worth naming is persistence plumbing. The readme points at a single mounted directory for state, mentions zero telemetry and an MIT licence, and links a page on data ownership, but it does not give an export command, a backup command, or a restore procedure. For a private log that is the kind of data people keep for years, that omission is the thing to resolve in the deployment guide before the first note goes in.

## The web clipper writes source-linked Markdown, and its pairing is undocumented here

The browser extension is the part of Memos aimed at capture from elsewhere. It saves pages, selections, and images from the browser straight into Memos as source-linked Markdown, and it exists as a Chrome extension and a Firefox add-on. Source-linked is the useful property: a clipped page keeps the pointer back to where it came from, so a memo assembled from someone else's writing is distinguishable later from your own thought, which matters in a chronological log where every entry otherwise looks alike.

What is not stated is how the extension authenticates against a self-hosted instance. A clipper on a personal machine talking to a container on your own network is a different trust question from an extension talking to a shared host, and the readme gives no token, no URL setting, and no permission model for it. The live demo at demo.usememos.com is the fastest way to see what a clipped entry looks like before committing, and the docs at usememos.com/docs are where the pairing details belong.

## A Go service with agents, context and ownership files at the root

The top level of the repository is a good map of what maintainers expect contributors to touch: `cmd/`, `core/`, `internal/`, `server/`, `store/`, `proto/`, `web/`, `markdown/`, `filter/`, `provider/`, `scripts/`, and `docs/`. A `proto/` directory alongside gRPC, the gateway, and connectrpc in the module file means the service surface is defined as an interface, which is what makes an API client and the Web Clipper possible rather than accidental. `provider/` sits next to it, and the S3 client in the module file suggests object storage is part of the design.

Alongside the code sit `AGENTS.md`, `CONTEXT.md`, `CODEOWNERS`, `SECURITY.md`, and a `.golangci.yaml`. Two of these matter to anyone other than a contributor: SECURITY.md is where vulnerability reporting goes, and CODEOWNERS says which areas have owners, which is a fast way to see where review attention sits before filing an issue. Development is active, with the last push landing on 2026-09-28 and v0.31.0 published on 2026-09-19, and the contributing guide is linked from the readme for anyone joining that work.

## Conclusion

People who want a private, chronological note log on infrastructure they already control will find the quick start sufficient to try it, and should first read the deployment guide for anything the four flag command leaves out, including TLS and backups. Anyone upgrading an instance older than v0.31.0 must stage through v0.31.0 and read store/migration/README.md first, and anyone pinning a build should pin a digest or a specific tag, since the Docker stable tag moves.

## FAQ

### What is Memos, the self-hosted app?

It is a self-hosted home for short-form thinking: daily notes, links, work logs, and snippets land in a chronological Markdown timeline on infrastructure you control, with no title, folder, or template required at capture time.

### How do I install Memos?

The quick start runs one detached container named memos, publishing port 5230 and mounting ~/.memos to /var/opt/memos, using the neosmemo/memos:stable image, and other install options are in the deployment guide at usememos.com/docs/deploy.

### How do I use Memos once it is running?

Write in Markdown, attach media, and save without picking a title, folder, or template, then find entries again through the timeline, search, tags, and pins, and keep each memo private or publish only the ones you choose.

### Is the project spelled memo or memos?

Memos, plural. The module path is github.com/usememos/memos, the Docker image is neosmemo/memos, and the site is usememos.com, so a pin or an image reference has to use the plural form.

## Sources

- [Official documentation](https://usememos.com)
- [Official README](https://github.com/usememos/memos#readme)
- [Project repository](https://github.com/usememos/memos)
- [Release notes](https://github.com/usememos/memos/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/usememos-memos
