Richy1989/keepIT
GitHub: Richy1989/keepIT
keepIT 是一款支持实时同步、用户间笔记共享、提醒功能及原生 Android 离线应用的自托管笔记应用。
Stars: 13 | Forks: 0

# keepIT
**一款现代化的实时笔记应用,你可以自行部署。**
[](https://hub.docker.com/r/richy1989/keepit)
[](#android-应用)
[](LICENSE)

老实说?我只是想要一款简单的笔记应用,但却找不到一款同时具备我真正看重的三个要素的软件——所以我干脆自己动手做了一个。借助一点 AI 的帮助 😉,现代的问题就需要现代的解决思路。
我真正想要的功能:
- 一款拥有现代化 Web UI 的简单笔记应用
- 不同用户之间的笔记共享
- 原生 Android 应用,并包含主屏幕小组件
如今,它已经发展成一款极速运行的应用,具备乐观编辑、列表、搜索、共享以及**实时同步**功能——因此,在一台设备上编辑的笔记会无需刷新即可显示在你的其他设备上。我对目前的成果非常满意。
## 目录
- [你可以用它做什么](#what-you-can-do-with-it)
- [运行你自己的 keepIT](#run-your-own-keepit)
- [Android 应用](#the-android-app)
- [下一步计划](#whats-next)
- [面向开发者](#for-developers)
- [支持](#support)
- [License](#license)
## 你可以用它做什么
- 📝 **随心所欲写笔记** —— 快捷的文本笔记支持富文本格式(粗体、标题、列表、链接、代码),或者是可以随时勾选的清单。
- 🗂️ **保持条理** —— 将笔记分组到列表中,将重要的笔记置顶,归档已完成的内容,并通过搜索即时找到任何内容。已删除的笔记会留在回收站,直到你确认无误。
- 🎨 **个性定制** —— 为任意笔记设置背景颜色,并为整个应用挑选你喜欢的强调色。
- ⏰ **提醒功能** —— 为任意笔记设置提醒,可以是单次提醒或按计划提醒(每日、每周、每月、每年)。在手机上,它们会以真实的系统通知形式送达——即使应用被关闭、屏幕已锁定或没有网络也能收到。
- 👥 **共享笔记** —— 通过电子邮件邀请他人查看或与你共同编辑笔记。你们各自保留自己的置顶、列表和提醒;而编辑内容会实时展示给所有人。
- 🔄 **时刻同步** —— 在一台设备上更改笔记,看着它在你的其他设备上更新,无需任何刷新。
- 📱 **内含 Android 应用** —— 在手机上同步相同的笔记,并附带用于查看最近笔记和一键速记的主屏幕小组件。它完全支持离线工作:随时随地阅读和编辑,一旦联网更改即会同步。
- 🔒 **笔记只属于你** —— keepIT 是自托管的。所有数据都存放在**你自己的**服务器上,没有第三方云服务,除了你自己,不需要在任何地方注册账号。
*即将推出:笔记中的照片和图片 —— 请查看[下一步计划](#whats-next)。*
## 运行你自己的 keepIT
keepIT 可以通过 **Docker** 运行在你自己的机器或家庭服务器上。只需一条命令,无需设置数据库:
```
docker run -d \
--name keepit \
-p 8080:80 \
-v keepit-data:/data \
-e Jwt__Key="your-random-secret-at-least-32-chars" \
richy1989/keepit:latest
```
然后打开 **http://localhost:8080**(或者你服务器地址的 8080 端口)并创建你的账号。就这么简单。
一些值得了解的事项:
- **`Jwt__Key`** 是保护你登录安全的密钥 —— 请将其替换为至少 32 个字符的任意随机字符串,并在重启时保持其不变。
- **你的数据** 存放在 `keepit-data` volume 中 —— 备份它就等于备份了你的笔记。
- **一旦你的账号创建完毕**,你可以通过添加 `-e App__AllowRegistration=false` 来关闭公开注册 —— 如果你的服务器可以从互联网访问,强烈建议这样做。
- **忘记密码** 功能无需任何邮件服务器即可工作:重置链接会被写入服务器日志(`docker logs keepit`)中,作为运营者的你可以从中获取它。如果希望通过邮件发送给用户,请使用下方的 `Email__*` 设置配置 SMTP。
- 正在运行 **Unraid**?仓库中已包含一个 Community Apps 模板,位于 [`deploy/keepit.unraid.xml`](deploy/keepit.unraid.xml)。
更喜欢使用 Docker Compose、Postgres,或者自己构建镜像?
**Docker Compose**(三个容器:app、web server 和一个 PostgreSQL 数据库)—— 在克隆此仓库后运行:
```
cp .env.example .env # set JWT_KEY (32+ chars), optionally POSTGRES_PASSWORD
docker compose up -d --build # builds everything locally, then starts the stack
```
打开 **http://localhost:8080**。数据将持久化存储在指定的 Docker volume 中。
在**单个容器中使用 PostgreSQL** 代替内置数据库 —— 你可以使用离散变量(`POSTGRES_HOST` 是开关;端口/数据库/用户默认值为 `5432`/`keepit`/`keepit`):
```
docker run -d \
--name keepit \
-p 8080:80 \
-v keepit-data:/data \
-e Jwt__Key="your-secret" \
-e POSTGRES_HOST= \
-e POSTGRES_PASSWORD= \
richy1989/keepit:latest
```
……或者完整的连接字符串(如果两者都设置了,连接字符串优先):
```
docker run -d \
--name keepit \
-p 8080:80 \
-v keepit-data:/data \
-e Jwt__Key="your-secret" \
-e "ConnectionStrings__Postgres=Host=;Port=5432;Database=keepit;Username=keepit;Password=" \
richy1989/keepit:latest
```
**自己构建镜像**(无需 Docker Hub):
```
docker build -f deploy/Dockerfile -t keepit:local .
docker run -d --name keepit -p 8080:80 -v keepit-data:/data \
-e Jwt__Key="your-random-secret-at-least-32-chars" keepit:local
```
所有设置(环境变量)
| 变量 | 必需 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `Jwt__Key` | **是** | — | 随机密钥,至少 32 个字符 —— 保护登录安全。**这是应用实际读取的变量**;请在执行 `docker run` / Unraid / 单容器镜像时使用它。 |
| `JWT_KEY` | 仅 compose | — | 方便的 `.env` 值,`docker-compose.yml` 会将其作为 `Jwt__Key` 传递。应用本身不直接读取此变量。 |
| `ConnectionStrings__Postgres` | 否 | *(内置 SQLite)* | 完整的 Postgres 连接字符串。如果此变量和 `POSTGRES_HOST` 都未设置,则使用无需任何配置的 SQLite 数据库。优先级高于下方离散的 `POSTGRES_*` 变量。 |
| `POSTGRES_HOST` | 否 | — | Postgres 主机 —— 完整连接字符串的更友好替代方案:设置此变量会将 API 切换为由 `POSTGRES_*` 变量构建的 Postgres。 |
| `POSTGRES_PORT` | 否 | `5432` | Postgres 端口(仅限离散设置)。 |
| `POSTGRES_DB` | 否 | `keepit` | Postgres 数据库名称(仅限离散设置)。 |
| `POSTGRES_USER` | 否 | `keepit` | Postgres 用户名(仅限离散设置)。 |
| `POSTGRES_PASSWORD` | 否 | `keepit` | Postgres 密码。API 在离散设置中会读取它,同时 Compose stack 也会为 `db` 服务及其交给 API 的连接字符串读取它。 |
| `App__AllowRegistration` | 否 | `true` | 是否允许创建新账号。在暴露于互联网的实例上:先注册你自己的账号,然后设置为 `false` 以关闭公开注册。 |
| `App__DataRoot` | 否 | `./App_Data` | 用于存放数据库、安全密钥和媒体文件的目录。 |
| `App__ForwardedProxyHops` | 否 | `1` | 应用前端受信任的反向代理跳数 —— 上文的基础设置为 `1`,如果你在前面又加了一层代理(例如 Traefik),则设置为 `2`。 |
| `App__PublicBaseUrl` | 否 | *(自动检测)* | 你实例的公开地址(例如 `https://notes.example.com`),用于生成密码重置链接。通常会从请求中自动检测;如果重置链接指向了错误的主机,请手动设置。 |
| `Email__SmtpHost` | 否 | — | 用于发送外发邮件(密码重置链接)的 SMTP 服务器。留空则在不发送邮件的情况下运行 —— 重置链接将记录在服务器日志中。 |
| `Email__From` | 需配合 SMTP | — | 发件人地址,例如 `keepIT `。设置 `Email__SmtpHost` 后必填。 |
| `Email__SmtpUsername` | 否 | — | SMTP 登录用户名。留空(连同密码一起)表示使用无需身份验证的中继。 |
| `Email__SmtpPassword` | 否 | — | SMTP 登录密码,与 `Email__SmtpUsername` 配对使用。 |
| `Email__SmtpPort` | 否 | `587` | SMTP 端口 —— `587` 用于 STARTTLS 提交,`465` 用于隐式 TLS(同时也需设置 `Email__UseStartTls=false`)。 |
| `Email__UseStartTls` | 否 | `true` | `true` = STARTTLS(端口 587);`false` = 隐式 TLS(端口 465)。 |
| `Auth__RefreshCookie__Secure` | 否 | `true` (Compose) / `false` (单容器) | 登录 cookie 是否仅限 HTTPS。在 TLS 环境下保持为 `true`;仅在通过纯 HTTP 服务于非 localhost 地址(例如没有 TLS 的局域网 IP)时才设置为 `false`。 |
| `Jwt__Issuer` / `Jwt__Audience` | 否 | `keepITCore` / `keepIT.api` | 高级设置:token claims。 |
| `Jwt__AccessTokenMinutes` / `Jwt__RefreshTokenDays` | 否 | `15` / `14` | 高级设置:登录 token 的有效时长。 |
| `ASPNETCORE_ENVIRONMENT` | 否 | `Production` | 设置为 `Development` 可获取详细日志记录,并在 `/scalar/v1` 使用 API explorer。 |
Compose stack 会自动设置其中大部分变量,并且仅从 `.env` 读取五个值:`JWT_KEY`、`POSTGRES_PASSWORD`、`REFRESH_COOKIE_SECURE`、`FORWARDED_PROXY_HOPS` 和 `ALLOW_REGISTRATION`。
## Android 应用
位于 [`app/`](app) 中的应用将你的笔记带到了手机上:离线优先、实时同步、原生提醒通知,以及一个主屏幕小组件。它(暂时)还没有上架 Play Store,所以你需要自己构建并安装它 —— 在 **Android Studio** 中打开 `app/` 目录,或者通过命令行操作(需要 Android SDK):
```
cd app
./gradlew :app:assembleDebug # build the APK
./gradlew :app:installDebug # or install straight onto a connected phone
```
首次启动时,在登录界面输入你的**服务器地址** —— 即你在浏览器中打开的同一个 URL(从 Android 模拟器访问你自己的机器,地址为 `http://10.0.2.2:5025`)。为了确保在手机休眠时提醒也能分秒不差地触发,请在应用的设置界面中授予 **Alarms & reminders** 权限。
## 下一步计划
- 🖼️ **笔记中的照片和图片** —— 支持附加图片,并可将图片用作笔记的背景。
- 📤 **从手机端分享** —— 直接在 Android 应用中邀请他人查看笔记。
- ✉️ **邀请任何人** —— 与尚未注册的人分享笔记。
## 面向开发者
对它的实现原理感兴趣或者想要进行二次开发?**[`ARCHITECTURE.md`](ARCHITECTURE.md)** 包含了完整的设计和构思。简短版本是:由 ASP.NET Core (.NET 10) 构建 REST API + SignalR 实现实时通信,Web 端使用 React 19/TypeScript 应用,Android 端则是 Kotlin/Jetpack Compose 应用 —— 它们都调用同一个 API,其中 C# DTOs 作为契约的唯一事实来源(类型化的 TS 客户端是通过 OpenAPI 生成的:`cd web && npm run generate:api`)。
使用 **.NET 10 SDK** 和 **Node.js 22+** 在本地运行它(无需设置数据库 —— 会自动创建一个 SQLite 开发数据库):
```
# 1) Backend — http://localhost:5025 (Scalar API UI 位于 /scalar/v1)
dotnet run --project keepIT/keepITCore
# 2) Frontend — http://localhost:5173 (将 /api 代理到 Backend)
cd web && npm install && npm run dev
```
打开 **http://localhost:5173** 并注册一个账号 —— 或者通过运行脚本填充测试数据(`test@test.com` / `Test1234#1234`,以及一些列表和各种笔记):
```
./scripts/seed-dev-data.sh # PowerShell twin: ./scripts/seed-dev-data.ps1
```
## 支持
keepIT 是完全免费且自托管的 —— 没有账号限制,也不需要订阅。如果它对你有帮助并且你想表示感谢,可以[**请我喝杯咖啡** ☕](https://buymeacoffee.com/hyperstarit)。非常感激,但绝不强求。
## License
基于 [MIT License](LICENSE) 发布 —— © 2026 Richard Leopold。可免费使用、修改和分发;只需保留版权和许可声明即可。
标签:Android应用, Docker, 安全防御评估, 实时同步, 测试用例, 笔记应用, 自托管, 请求拦截