What is Memos?#

Memos is an open source web application for writing, organizing, and sharing short notes. Here it is running on one of our Digital Ocean droplets in Nomad behind IO.

Look at this beautiful sign-in screen!

As you might guess, Memos is a note-taking app that supports OAuth-based signin (along with optional usernames and passwords). Memos is nicely configurable and can use a small variety of database backends that includes SQLite, which is perfectly fine for even the busiest self-hosting note taker.
How I Run Memos#
With Nomad#
I’m running Memos in a droplet that I manage with Nomad just as described in Droplet Superpowers.
Here’s memos.hcl
, which I apply with nomad job run memos.hcl
:
job "memos" {
datacenters = ["dc1"]
type = "service"
group "memos" {
count = 1
network {
port "http" { to = 3000 }
}
service {
name = "memos"
provider = "nomad"
port = "http"
}
volume "memos" {
type = "host"
read_only = false
source = "memos"
}
task "memos" {
driver = "docker"
config {
image = "neosmemo/memos:stable"
ports = ["http"]
force_pull = true
}
env {
MEMOS_MODE = "prod"
MEMOS_PORT = 3000
}
volume_mount {
volume = "memos"
destination = "/var/opt/memos"
read_only = false
}
}
}
}
This needs a host volume, which I described with an addition to the client
block in my /etc/nomad.d/nomad.hcl
:
host_volume "memos" {
path = "/srv/nomad/memos"
read_only = false
}
If you’ve been doing this, you also know that you need to create the /srv/nomad/memos
directory on your droplet.
With the job running, this is what I see in the Nomad console:

If I drill down to see the allocation, I can see that it’s running well below the default 300MB memory allocation for Nomad jobs. I’ll probably tighten the memory budget in my job description later.

Behind IO#
Memos is running an insecure server inside my cluster using HTTP. I publish that to the internet using an IO ingress. The configuration for that is really simple:
host "memos.agentio.dev" {
name = "memos"
backend = "nomad:memos"
}
I put that in a file named memos.hcl
and installed it in my IO with scp
.
scp -P 8022 memos.hcl agentio.dev
This needs an SSL certificate, and as discussed elsewhere, IO can get that for me from LetsEncrypt.
Observing Memos Traffic#
Because I’m running the Memos app behind IO, all of its traffic is captured and viewable in IO. Here I’ve connected to the IO running this ingress and expanded the list of traffic to the Memos app.

That list revealed lots of traffic that appears to be API calls. Picking one with ListMemos
in the path, I expand the traffic item to see the request and response headers.

This is gRPC Web traffic, and this is how I learned that Memos uses gRPC! The messages are binary-encoded protocol buffers, which generally can’t be parsed without a schema description, but there’s an easy way to do that with IO. First I need the descriptors, which I can get by compiling the protos in the usememos/memos repo. I run this script in the protos
directory.
#!/bin/sh
protoc -I . -I ~/Desktop/googleapis/googleapis \
--include_imports \
api/v1/activity_service.proto \
api/v1/auth_service.proto \
api/v1/attachment_service.proto \
api/v1/user_service.proto \
api/v1/idp_service.proto \
api/v1/common.proto \
api/v1/markdown_service.proto \
api/v1/workspace_service.proto \
api/v1/shortcut_service.proto \
api/v1/inbox_service.proto \
api/v1/memo_service.proto \
-odescriptor.pb
Then I upload the descriptor to my IO with scp
.
scp -P 8022 descriptor.pb agentio.dev
That puts the Memos type descriptions in IO’s internal protobuf registry and allows IO to display the contents of Memos API requests and responses. Here’s the response body of that ListMemos
request:

Memos Rocks!#
Needless to say, I’m very impressed with this little note-taking project. It has lots of qualities that I find appealing:
- The code is available at usememos/memos with the MIT License.
- It’s got a good base (gRPC, Go)
- It’s up to v0.25.x
- It runs well in a container
- It can use SQLite
- It stores attachments in a reasonable way
- I could probably patch and contribute to it
- It could provide good patterns for similar apps (e.g. photo-sharing)
But, yeah, there are a few things that I don’t love:
- The main Memos authors are pseudonymous.
- The Memos API is unstable (the mobile apps are currently broken because some method names changed for v0.25).
- Memos is a rabbit hole. Yeah, I could really get drawn into work on this.
- Now that I’ve tasted ATProto auth, I really hate having to register OAuth clients to use providers like GitHub. Memo needs some work to support ATProto auth.
- The Memos build process depends on Buf and the protos are hard to compile without Buf.
Nonetheless, I’m planning to keep using my Memos deployment for a while as a scratchpad for work in progress related to IO. Posts are generally “protected” (visible only to signed-in users), but I’ve left it open for anyone to sign in with GitHub OAuth. Come see us at memos.agentio.dev.