Host it yourself
rememd keeps your PRDs, session logs and notes. Run the server yourself and none of it leaves your infrastructure. There is no hosted option — this is the way it is meant to run.
One server is one organisation: a single admin, everyone else joins by invite. There is no multi-tenancy to configure.
This is a write-up of something that runs. api.rememd.com is a €4/month VPS in Helsinki set up exactly this way, and every trap below cost real time on it.
What you need
- A machine with a public IP — a €4/month VPS is plenty
- A domain pointed at it (
api.example.com), with ports 80 and 443 open - About ten minutes
Caddy obtains and renews the TLS certificate automatically. You do not handle certificates.
The box
Nothing here is rememd-specific, and if you already run servers you have your own version of it: a non-root user, key-only SSH, automatic security updates, and a provider-level firewall allowing 80 and 443.
Getting the server
One static binary. CGO_ENABLED=0, so it runs on musl and glibc alike and there is no distribution matrix, and the migrations travel inside it — there is no separate schema step and nothing to keep in sync.
curl -fsSLo rememd-backend https://github.com/<releases-repo>/releases/latest/download/rememd-backend-linux-amd64
chmod +x rememd-backendIt needs a Postgres to point at and three environment variables. Run it behind anything that terminates TLS.
DATABASE_URL=postgres://rememd:PASSWORD@localhost:5432/rememd?sslmode=disable \
REMEMD_ADMIN_TOKEN=$(openssl rand -hex 32) \
REMEMD_PUBLIC_URL=https://api.example.com \
PORT=8089 ./rememd-backendOr with Docker, which handles TLS for you
The fuller route: Postgres, the server and Caddy together, with certificates obtained and renewed automatically. Two files, both shown here in full — there is nothing to clone.
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: rememd
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set this in .env}
POSTGRES_DB: rememd
volumes:
- rememd-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U rememd"]
interval: 5s
timeout: 3s
retries: 20
restart: unless-stopped
# No ports: on purpose. See the trap below — a host firewall will not save you.
server:
image: ${REMEMD_IMAGE:?set this in .env}
environment:
DATABASE_URL: postgres://rememd:${POSTGRES_PASSWORD}@db:5432/rememd?sslmode=disable
REMEMD_ADMIN_TOKEN: ${REMEMD_ADMIN_TOKEN:?set this in .env}
REMEMD_PUBLIC_URL: https://${REMEMD_DOMAIN:?set this in .env}
TZ: ${REMEMD_TZ:-UTC}
PORT: "8089"
depends_on:
db: { condition: service_healthy }
restart: unless-stopped
caddy:
image: caddy:2-alpine
ports: ["80:80", "443:443"]
environment:
REMEMD_DOMAIN: ${REMEMD_DOMAIN}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
depends_on: [server]
restart: unless-stopped
volumes:
rememd-db:
caddy-data:
caddy-config:{$REMEMD_DOMAIN} {
reverse_proxy server:8089 {
# /events is Server-Sent Events, held open for the life of a session.
# Caddy streams without buffering by default; stating it means a future
# tweak cannot silently start batching live updates into nothing.
flush_interval -1
}
encode gzip
# The API answers with its own JSON errors; Caddy should not dress them up.
handle_errors {
respond "{err.status_code} {err.status_text}"
}
}REMEMD_DOMAIN=api.example.com
REMEMD_ADMIN_TOKEN=<openssl rand -hex 32>
POSTGRES_PASSWORD=<openssl rand -hex 32>
REMEMD_TZ=Europe/Stockholm
REMEMD_IMAGE=<the published image>docker compose up -dCheck it
curl https://api.example.com/healthzThe first request may take a few seconds while Caddy gets its certificate. If it hangs, DNS is not pointing here yet or 80/443 are closed — Caddy needs both to complete the ACME challenge.
/healthz reports the build: commit and build time. Checking it after a deploy is the only thing that catches a pull that did not take, which is otherwise silent and indefinite.
Connecting your own client
You are the admin, so you do not use an invite. Write the credential file:
{"server": "https://api.example.com", "token": "<the admin token>"}Then relaunch the app. There is no mode to set.
Adding people
From the app: right-click any row in the tree → Invite → pick a level → Create invite link. Send them the link; they run the command it shows.
A grant can be a whole workspace, a product, a focus area or a single feature, and the server enforces it — a scoped member’s index is pruned before it leaves the machine, and their saves are merged back so they cannot delete what they cannot see.
The MCP connector
The server also speaks MCP over Streamable HTTP at /mcp, so it can be added to Claude as a custom connector and reached from Claude Desktop and the Claude app — not only from a terminal.
Add it once at claude.ai by URL: https://api.example.com/mcp. Claude registers itself, sends you to a consent page, and asks for a rememd access token. The connection gets its own credential, which can be revoked on its own. You cannot add a server from a phone — register on the web and it becomes available there.
Backups
A dump and a prune, on a cron. Nothing rememd-specific — it is a Postgres database and every tool you already trust works on it.
0 4 * * * cd /srv/rememd && docker compose exec -T db pg_dump -U rememd rememd | gzip > backups/rememd-$(date +\%Y\%m\%d).sql.gz && find backups -name 'rememd-*.sql.gz' -mtime +14 -deleteNote the escaped percent signs — cron treats a bare % as a newline, which turns the command into one that silently writes an empty file.
A dump beside the database protects you from a bad migration but not from losing the machine. Copying it somewhere else is your job.
gunzip -c backups/rememd-<stamp>.sql.gz | docker compose exec -T db psql -U rememd rememdTest that on a throwaway database before you need it. An untested backup is a guess.
Upgrading
Do not build the image on the server. It compiles the Swift MCP server, which wants far more CPU and memory than a small VPS has, and the failure at the end of a long build is an unhelpful one.
docker compose pull && docker compose up -dMigrations run at startup, so there is no separate step. Take a backup first.