> ## Content Index
> Fetch the complete content index at: https://blog.uptime.bet/llms.txt
> Use this file to discover other available public pages before exploring further.

# Ech0 5.9: Run Your Own Lightweight Microblog for Homelab Notes with Docker Compose
- URL: https://blog.uptime.bet/ech0-self-hosted-microblog-docker/
- Published: 2026-11-05T09:19:14.000Z
- Updated: 2026-11-05T09:19:14.000Z
- Description: Ech0 is a tiny self-hosted microblog for short Markdown posts with RSS, private posts and comments. We tested v5.9.4 with Docker Compose, checked that private posts stay private and found a few defaults you should change.
- Author: Alexandre Nebeling
- Tags: Trending, Self-Hosted, Open Source, Docker, Homelab, Blogging

Some thoughts are too short for a blog post and too public for a private notes app. "Finally fixed the backup job." "This Compose flag saved me an hour." A link with two sentences of context. A lot of us post that kind of thing on a social network, where it belongs to someone else's platform.

**Ech0** (with a zero) is a self-hosted answer to that. It's a personal microblog: a timeline of short Markdown posts, called Echos, that you publish on your own domain, with RSS, optional comments and a small admin panel. It is written in Go, stores everything in SQLite and runs as a single container. The project is moving quickly right now, with **v5.9.4** released on November 4, 2026, the third release that day. We set it up on a fresh test VM to see what you get.

## What is Ech0?

The project lives on GitHub at `lin-snow/Ech0`, has a little over 2,000 stars and is licensed under **AGPL-3.0-or-later**. The maintainers also offer a separate commercial license, but that is only relevant if you want to build a closed-source product or hosted service on top of Ech0\. For personal use under the AGPL terms, you don't need it.

The README compares it with Memos, and that's a useful mental model. Memos is mostly about capturing notes for yourself. Ech0 is about publishing them: a timeline that other people can read, follow via RSS and, if you allow it, comment on.

According to the README, the feature list includes:

- Markdown posts with tags, link cards and embedded YouTube or Bilibili videos
- Image, audio and video attachments, stored locally or on S3-compatible storage
- Public and private posts, an RSS feed and a built-in comment system with moderation
- Passkeys, OAuth2/OIDC login and scoped access tokens for the API
- Export and backup from the web UI, a CLI and a terminal UI, plus "capsules" that can be imported elsewhere or turned into a static site
- Webhooks, an MCP server and an optional AI assistant that works on your own posts

We didn't test everything on that list. What we did test is described below.

### What's new in 5.9

The last few patch releases are worth knowing about. **5.9.2** reworked how sessions and access tokens are authorized. The changelog asks administrators to sign in again and to recreate access tokens used by scripts, the CLI and MCP clients. It also added standard OAuth 2.1 authorization for MCP clients. **5.9.3** added a first-run checklist, and **5.9.4** polished the setup page, fixed media links in the RSS feed so that feed readers can load attached images, and added a landing page for browsers that open the feed URL.

## Requirements

- A Linux host with Docker Engine and the Docker Compose plugin. Images are published for amd64 and arm64.
- Barely any RAM. Ech0 used less than 25 MiB in our test.
- For real use: a domain such as `ech0.example.com` and a reverse proxy with TLS.

## Installing Ech0 with Docker Compose

We tested the following steps on a fresh Ubuntu 24.04 VM with 2 vCPUs and about 1.8 GB of RAM. The only difference to our test was the host port.

### Step 1: Create a folder and a secret

```bash
mkdir -p ~/ech0
cd ~/ech0
echo "JWT_SECRET=$(openssl rand -hex 32)" > .env
chmod 600 .env
```

Ech0 signs its login tokens with `JWT_SECRET`. Note that the variable has no `ECH0_` prefix, unlike most other settings (`ECH0_JWT_SECRET` works as an alias). If you don't set it at all, Ech0 generates a random secret on every start, which means everyone gets logged out whenever the container restarts.

Don't copy the secret from the official examples. The README, the release notes and the sample Compose file all use the same placeholder string, and since the tokens are signed with HMAC (HS256), anyone who knows the secret can create valid tokens themselves. The sample Compose file also writes it as `JWT_SECRET="Hello Echos"` in list syntax, where Compose keeps the double quotes as part of the value. That is harmless in itself, but it's one more reason to set your own value.

### Step 2: Write the Compose file

Create `compose.yaml`:

```yaml
services:
  ech0:
    image: sn0wl1n/ech0:v5.9.4
    container_name: ech0
    restart: unless-stopped
    ports:
      - "127.0.0.1:6277:6277"
    volumes:
      - ./data:/app/data
    environment:
      - JWT_SECRET=${JWT_SECRET}
```

Compared with the official sample, we pinned the version instead of using `latest`, dropped the obsolete `version:` key, added a restart policy and bound the port to `127.0.0.1` so that only your reverse proxy can reach it. Port 6277 is Ech0's default.

Everything Ech0 stores ends up in `./data`: the SQLite database `ech0.db`, uploaded files under `files/` and a log file. That one folder is what you need to back up.

### Step 3: Start it

```bash
docker compose up -d
docker compose logs ech0
```

On our VM the web UI answered a few seconds after `docker compose up` returned. The log starts with an ASCII banner that shows the version and port, followed by JSON log lines from the database migrations. There were no warnings.

### Step 4: Claim the instance

The README still says the first *registered* account becomes the owner. In 5.9.4 the UI handles this differently: on a fresh instance, every visit was redirected to `/init`. That page asks for an owner email, a username, a password and an optional site name. After clicking **Initialize** we were logged in and landed on the publish tab.

![Ech0 first-run page asking for owner email, username, password and site name](https://blog.uptime.bet/content/images/2026/11/ech0-5-9-init.png)

The first-run page creates the owner account. Ech0 5.9.4 running on our test VM (demo data). Screenshot: uptime.bet

As with most self-hosted apps, the owner is whoever completes this form first. Do it right after the first start, before you put the instance on the internet.

## Using Ech0

Writing a post is simple: a text box, a button for attachments, one for tags and a publish button. Clicking publish opens a small menu with two choices, **Publish as public** and **Publish as private**. We posted three public Echos and one private one. Markdown worked as expected, including lists and inline code.

![Ech0 timeline for the logged-in owner with a setup checklist and several posts](https://blog.uptime.bet/content/images/2026/11/ech0-5-9-owner-feed.png)

The owner's view of the timeline, with the first-run checklist from 5.9.3 on top. Ech0 5.9.4 running on our test VM (demo data). Screenshot: uptime.bet

The first-run checklist on top has three items: write your first Echo, name your site and set your site address. The last one matters more than it looks, because Ech0 uses that address to build RSS and share links, so set it to your real domain.

We then checked the private post from the outside. In a logged-out browser session it did not show up in the timeline, the public API returned only the three public posts, and the RSS feed had three entries. So the private flag also applies to the feed, not just to the web UI.

![Public Ech0 timeline as seen by a logged-out visitor with three posts](https://blog.uptime.bet/content/images/2026/11/ech0-5-9-public-timeline.png)

What a visitor sees: the private post is gone. Ech0 5.9.4 running on our test VM (demo data). Screenshot: uptime.bet

The **Settings** link opens an admin panel with a dashboard (post counts, a seven-day activity chart and visitor stats) and sections for users, storage, data, comments, SSO, extensions, integrations and logs.

![Ech0 admin dashboard with post counts, activity log and visitor statistics](https://blog.uptime.bet/content/images/2026/11/ech0-5-9-dashboard.png)

The admin dashboard. Ech0 5.9.4 running on our test VM (demo data). Screenshot: uptime.bet

## What we observed on the test VM

- **Memory:** `docker stats` showed about 15.5 MiB right after the start and between 17 and 20 MiB after we had published posts and clicked through the UI.
- **Image size:** 151 MB on disk after the pull. The image is based on Alpine Linux.
- **Restarts:** after `docker restart`, the browser session was still logged in and all posts were still there. With a fixed `JWT_SECRET`, that's what should happen.
- **Language:** the UI is in English (four locales are available), but some API responses return Chinese status messages. You'll only notice if you work with the API directly.

## Tips

**Decide about registration.** On our fresh instance, the public settings reported `allow_register: true`, and we could create an account through the API without logging in. That account could not publish, though. Ech0 answered with a "no permission, contact the administrator" message, which matches the README's note that publishing is limited to privileged accounts by default. If you don't want strangers creating accounts at all, switch off **Allow registration** under Settings → System Settings.

**Environment variables are only first-boot defaults for many settings.** The configuration docs say that variables such as `ECH0_SETTING_*` and `ECH0_S3_*` are only written into the database on the first start. After that, change them in the admin panel. Port, database path, logging and the JWT secret are read from the environment on every start.

**Read the changelog before upgrading.** The 5.9.2 notes are a good example of why: scripts and integrations needed new access tokens after that update. With several releases in a single day, it pays to pin the version and upgrade on purpose.

**Back up `./data`.** SQLite runs in WAL mode here (we saw `ech0.db-wal` next to the database), so either stop the container before copying the folder or use Ech0's own export and backup features.

## Limits and security

- **The container runs as root.** The image doesn't define a non-root user, and `id` inside the container returned UID 0\. Files in `./data` are owned by root on the host. There's no Docker socket and no privileged mode involved, but it's worth knowing.
- **Keep it behind a reverse proxy.** Ech0 is meant to be public, so the usual rules apply: TLS, no exposed admin ports, updates when security fixes land.
- **Young, fast-moving project.** Three releases in one day means quick fixes but also breaking changes, like the token rework in 5.9.2\. The documentation sometimes lags behind the UI, as the `/init` example shows.
- **SQLite only.** The config docs state that `sqlite` is the only supported database type. For a personal microblog that's fine. Don't plan a large multi-author community on it.
- **Not a federated network.** Ech0 has its own way of connecting instances ("Connect" and "Explore"), which we didn't test. It's not ActivityPub, so your posts won't show up on Mastodon on their own.

## Ech0 vs. alternatives

**Memos** is the obvious comparison. It's much larger (over 60,000 stars on GitHub, MIT license) and very good at private, quick notes. If you mostly write for yourself, Memos is the safer choice. If you want a public timeline with RSS and comments, Ech0 is built for exactly that.

**WriteFreely** (AGPL-3.0) is a Markdown publishing platform for longer posts, with a focus on writers and communities. It's a better fit when your "short thoughts" are actually articles.

**A static site generator** or a full blog engine works too, of course. But opening a Git repository to post two sentences is a lot of friction. In Ech0, a post is a text box and a button.

## Conclusion

Ech0 is a narrow tool: a personal timeline on your own domain that needed less than 25 MiB of RAM in our test. Setup took a few minutes, private posts stayed private in every place we checked, and the admin panel covers what a single person needs.

Pick your own JWT secret, decide whether you want open registration, and keep an eye on the changelog. After that, it works well for the small homelab notes that never made it into a proper post.

If you're looking for something to post about, our guide to [Dagu, a self-hosted workflow scheduler](https://blog.uptime.bet/dagu-self-hosted-workflow-scheduler-docker/), might give you a few ideas.

## Sources

- [Ech0 on GitHub](https://github.com/lin-snow/Ech0?ref=blog.uptime.bet) (README, feature list)
- [Ech0 v5.9.4 release](https://github.com/lin-snow/Ech0/releases/tag/v5.9.4?ref=blog.uptime.bet) and [changelog](https://github.com/lin-snow/Ech0/blob/v5.9.4/CHANGELOG.md?ref=blog.uptime.bet)
- [Deployment guide](https://github.com/lin-snow/Ech0/blob/v5.9.4/DEPLOYMENT.md?ref=blog.uptime.bet) and [sample Compose file](https://github.com/lin-snow/Ech0/blob/v5.9.4/docker/docker-compose.yml?ref=blog.uptime.bet)
- [Configuration reference](https://github.com/lin-snow/Ech0/blob/v5.9.4/docs/usage/configuration.md?ref=blog.uptime.bet) (environment variables)
- [Commercial licensing notes](https://github.com/lin-snow/Ech0/blob/v5.9.4/COMMERCIAL.md?ref=blog.uptime.bet) and [LICENSE](https://github.com/lin-snow/Ech0/blob/v5.9.4/LICENSE?ref=blog.uptime.bet)
- [Docker image on Docker Hub](https://hub.docker.com/r/sn0wl1n/ech0?ref=blog.uptime.bet)
- [Official website and documentation](https://www.ech0.app/?ref=blog.uptime.bet)
- [Memos on GitHub](https://github.com/usememos/memos?ref=blog.uptime.bet), [WriteFreely on GitHub](https://github.com/writefreely/writefreely?ref=blog.uptime.bet)