From b915129dcf6c0043df3c629fe938986da661340f Mon Sep 17 00:00:00 2001 From: Karan Jayachandra Date: Fri, 31 Jul 2026 21:27:22 +0200 Subject: Added a memos instance --- CLAUDE.md | 6 +++++- README.md | 12 +++++++++++- hosts/eurovm/default.nix | 1 + modules/caddy.nix | 7 +++++++ modules/memos.nix | 24 ++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 modules/memos.nix diff --git a/CLAUDE.md b/CLAUDE.md index 6817d40..13310d0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -80,7 +80,7 @@ service module: - `caddy.nix` — the main thing that binds to 80/443 (see `adguard.nix` below for the one exception). Reverse-proxies each subdomain to a service's localhost port; the `dns.karanj.com` vhost additionally serves the ACME HTTP-01 webroot for `acme.nix`. Application ports (5006, - 8080, 8086) are bound to `127.0.0.1` and never exposed directly — Caddy is the public HTTP(S) + 5230, 8080, 8086) are bound to `127.0.0.1` and never exposed directly — Caddy is the public HTTP(S) entry point for everything except AdGuard's encrypted-DNS ports, and handles Let's Encrypt automatically for its own certs. - `adguard.nix` — AdGuard Home; plain DNS (`dns.port`) is set to `0` and deliberately not opened @@ -108,6 +108,10 @@ service module: - `actual.nix` — Actual Budget via the native `services.actual` module (ships in this flake's pinned nixpkgs). No secrets involved; the server password is set interactively on first browser visit. +- `memos.nix` — Memos note-taking app via the native `services.memos` module (ships in this + flake's pinned nixpkgs). Uses the module's default sqlite driver, so no separate database + service is needed (unlike Miniflux's Postgres). No secrets involved; the first account is + created interactively in the web UI on first visit. - `cgit.nix` — git hosting. Three-way access split: web browsing is public/unauthenticated via cgit, `git clone`/`pull` over HTTPS is public/read-only via `git-http-backend` + fcgiwrap, and `git push` is SSH-only through a dedicated `git` system user with its own authorized keys. cgit diff --git a/README.md b/README.md index 6cae516..d98fdb3 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ A flake-based, modular NixOS configuration for a personal server running in Euro | https://rss.karanj.com | Miniflux (RSS/Atom reader) | | https://budget.karanj.com | Actual Budget (personal finance) | | https://git.karanj.com | cgit (git repository browser) | +| https://notes.karanj.com | Memos (note-taking) | All services are reverse-proxied by **Caddy** with automatic TLS via Let's Encrypt. AdGuard also listens directly on **853/tcp** for DNS-over-TLS and **8443/tcp** for @@ -37,6 +38,7 @@ modules/ miniflux.nix Miniflux + PostgreSQL actual.nix Actual Budget cgit.nix cgit + fcgiwrap + git push user + memos.nix Memos (note-taking) ``` --- @@ -164,6 +166,7 @@ dns.karanj.com A rss.karanj.com A budget.karanj.com A git.karanj.com A +notes.karanj.com A ``` Or a single wildcard: `*.karanj.com A `. @@ -221,6 +224,7 @@ joined to your tailnet first), then: | Miniflux | https://rss.karanj.com | Log in with `admin` (or your `ADMIN_USERNAME`) + your sops password | | Actual Budget | https://budget.karanj.com | Set a server password in the browser on first visit - no pre-configuration needed | | cgit | https://git.karanj.com | No login needed - public read-only | +| Memos | https://notes.karanj.com | Create the first account directly in the web UI on first visit | To use the server as your device's DNS resolver, configure DNS-over-TLS or DNS-over-HTTPS as described under [AdGuard Home](#adguard-home) below - plain DNS (port 53) is disabled. @@ -312,6 +316,12 @@ and restart the service: `systemctl restart actual`. - **Clone/Pull:** `git clone https://git.karanj.com/.git` (public, read-only) - **Push:** SSH only - `git push git@:/srv/git/.git` +### Memos + +Data is stored as a sqlite database under `/var/lib/memos/`. No password reset flow needed +beyond what the web UI itself offers - it's a single-user instance with no separate admin +credentials in this config. + ### Caddy / TLS TLS certificates are obtained automatically from Let's Encrypt on first startup (registered to @@ -331,7 +341,7 @@ Caddy logs: `journalctl -u caddy -f` | 853 | TCP | DNS-over-TLS (AdGuard Home) | | 8443 | TCP | DNS-over-HTTPS (AdGuard Home) | -All other ports are closed at the firewall. App-level ports (5006, 8080, 8086) are bound to +All other ports are closed at the firewall. App-level ports (5006, 5230, 8080, 8086) are bound to 127.0.0.1 and never exposed directly. AdGuard's web UI (3000) binds all interfaces (required so its DoH/DoT listener - which shares the same bind host - reaches the public interface), but stays unreachable externally because the firewall never opens port 3000. diff --git a/hosts/eurovm/default.nix b/hosts/eurovm/default.nix index b487644..0181a07 100644 --- a/hosts/eurovm/default.nix +++ b/hosts/eurovm/default.nix @@ -12,6 +12,7 @@ ../../modules/miniflux.nix ../../modules/actual.nix ../../modules/cgit.nix + ../../modules/memos.nix ]; networking.hostName = "eurovm"; diff --git a/modules/caddy.nix b/modules/caddy.nix index f82c7f0..64418c3 100644 --- a/modules/caddy.nix +++ b/modules/caddy.nix @@ -37,6 +37,13 @@ ''; }; + # Memos - note-taking app + "notes.karanj.com" = { + extraConfig = '' + reverse_proxy 127.0.0.1:5230 + ''; + }; + # cgit - public read-only git viewer + smart HTTP for git clone/pull. # Both cgit browsing and git-http-backend (clone/pull) are served by # the same nginx vhost on 8086 - nginx itself routes between them by diff --git a/modules/memos.nix b/modules/memos.nix new file mode 100644 index 0000000..bc80e24 --- /dev/null +++ b/modules/memos.nix @@ -0,0 +1,24 @@ +{ config, ... }: + +# Memos - lightweight, privacy-first note-taking app. +# +# Native NixOS module (services.memos, available since this flake's pinned +# nixpkgs release). Listens on 127.0.0.1:5230; Caddy handles public HTTPS +# termination. Uses the module's default sqlite driver - no separate +# database service needed, unlike Miniflux's Postgres. +# +# No secrets involved: the first account is created directly in the web UI +# on first visit to https://notes.karanj.com. +{ + services.memos = { + enable = true; + settings = { + MEMOS_MODE = "prod"; + MEMOS_ADDR = "127.0.0.1"; + MEMOS_PORT = "5230"; + MEMOS_DRIVER = "sqlite"; + MEMOS_DATA = config.services.memos.dataDir; + MEMOS_INSTANCE_URL = "https://notes.karanj.com"; + }; + }; +} -- cgit v1.3.1