Android / Build, or is the channel already serving this? (push) Successful in 2s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 2s
Android / Core and FFI clippy and tests (push) Successful in 55s
CI & Build / Build now, or wait for Android? (push) Successful in 4s
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Successful in 2m25s
CI & Build / Web typecheck and unit tests (push) Successful in 12s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Python tests (push) Successful in 14s
CI & Build / integration (push) Successful in 2m20s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 3m29s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 4m27s
Desktop (Tauri) / Update manifest (push) Successful in 4s
Android / Kotlin + Rust (APK) (push) Successful in 9m17s
Android / Build the server image (push) Successful in 1s
#6227 "License Inkwell under AGPL-3.0-only: LICENSE file and SPDX identifier". The operator chose AGPL-3.0-only, as for FabledStash (#6212). - LICENSE is the canonical GNU AGPL v3 text from gnu.org: 661 lines, md5 eb1e647870add0502f8f010b19de32af, the same file as FabledStash's. - AGPL-3.0-only is declared in pyproject.toml, frontend/package.json (and its lockfile root entry), the four crates, and tauri.conf.json's bundle. - The pacman package declared MIT; it now declares AGPL-3.0-only. - pyproject's build floor moves to setuptools>=77, the first release that reads `license` as an SPDX expression. - The README's Licence section names the licence, links LICENSE, and states the network clause in one sentence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
165 lines
6.5 KiB
Markdown
165 lines
6.5 KiB
Markdown
<p align="center">
|
|
<img src="frontend/public/icon.svg" width="96" alt="Inkwell logo">
|
|
</p>
|
|
|
|
<h1 align="center">Inkwell</h1>
|
|
|
|
<p align="center">Capture a thought in under a second, and find it again later.</p>
|
|
|
|
Inkwell is a self-hosted notes app built around a Keep-style board of cards. Type
|
|
and it's saved; tag with `#words`, tick checklists, set reminders, attach files,
|
|
and search or browse by date when you need something back. It runs in the browser,
|
|
as a desktop app for Linux and Windows that works offline, and as an Android app,
|
|
all syncing with your own server.
|
|
|
|
## Quick start
|
|
|
|
Save this as `docker-compose.yml`, replace both `CHANGE_ME`s with the same password,
|
|
and run `docker compose up -d`:
|
|
|
|
```yaml
|
|
services:
|
|
db:
|
|
image: postgres:16-alpine
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: inkwell
|
|
POSTGRES_PASSWORD: CHANGE_ME
|
|
POSTGRES_DB: inkwell
|
|
volumes:
|
|
- inkwell-db:/var/lib/postgresql/data
|
|
|
|
app:
|
|
image: git.fabledsword.com/bvandeusen/inkwell:latest
|
|
restart: unless-stopped
|
|
depends_on:
|
|
- db
|
|
environment:
|
|
INKWELL_DATABASE_URL: postgresql+asyncpg://inkwell:CHANGE_ME@db:5432/inkwell
|
|
volumes:
|
|
- inkwell-data:/var/inkwell
|
|
ports:
|
|
- "5000:5000"
|
|
|
|
volumes:
|
|
inkwell-db:
|
|
inkwell-data:
|
|
```
|
|
|
|
Open `http://<host>:5000` and register. **The first account becomes the admin.**
|
|
|
|
The repository's own [docker-compose.yml](docker-compose.yml) is the same stack read
|
|
from a `.env` file; copy [.env.example](.env.example) to `.env` to use it.
|
|
|
|
## Configuration
|
|
|
|
| Variable | Required | What it is |
|
|
|---|---|---|
|
|
| `INKWELL_DATABASE_URL` | yes | The Postgres connection URL. |
|
|
| `INKWELL_SECRET_KEY` | no | Signs sessions. Unset, one is generated and kept in the database. |
|
|
| `INKWELL_LOG_LEVEL` | no | `INFO` by default. Sign-ins and other credential events log at INFO. |
|
|
|
|
Everything else — site name, sign-ups, email, attachment limits, trash retention,
|
|
link previews, backups, proxy hops — is set by the admin in **Settings**.
|
|
|
|
## Before you put it on the internet
|
|
|
|
Close registration, terminate TLS and forward `X-Forwarded-Proto`, stop publishing
|
|
the app port directly, and back up the attachment volume as well as the database.
|
|
[docs/public-hosting.md](docs/public-hosting.md) walks through each one, and lists
|
|
what the app already hardens on its own.
|
|
|
|
The browser only offers to install Inkwell as an app (PWA) over HTTPS or `localhost`.
|
|
|
|
## Updating and backups
|
|
|
|
- **Update:** `docker compose pull && docker compose up -d`. Migrations run on start.
|
|
- **Roll back:** pin `image: …/inkwell:<commit-sha>`. Every build on `main` publishes one.
|
|
- **Back up:** turn on scheduled backups in **Settings → Backups** (a folder, an
|
|
S3-compatible bucket, or Fabled Archives). See [docs/backups.md](docs/backups.md).
|
|
Otherwise back up both volumes: `inkwell-db` and `inkwell-data`.
|
|
|
|
## Features
|
|
|
|
**Capturing**
|
|
- A masonry board of cards. Start typing anywhere on it to write a new note.
|
|
- Notes save as you type; there is no save button.
|
|
- Checklists inside a note, ticked straight from the card.
|
|
- Images and files attached to a note, shown on its card; click an image to see it
|
|
full size or copy it back out.
|
|
- Paste a link and it gets a preview card.
|
|
- On the desktop, a global hotkey opens a small capture window over whatever you're doing.
|
|
- On Android, share text or images into Inkwell from any app.
|
|
|
|
**Organising**
|
|
- `#tags` written in the text become tags; a line of tags on its own is tidied away.
|
|
- Each tag gets a colour, and tags can be renamed, recoloured, merged and deleted.
|
|
- Pin, archive, drag to reorder.
|
|
- Trash with undo, emptied after a retention period the admin sets.
|
|
|
|
**Finding**
|
|
- Full-text search, combined with filters for tags, attachments and notes shared with you.
|
|
- A timeline that groups notes by when you wrote them.
|
|
- A command palette that jumps to any note by name.
|
|
- Version history: every editing session keeps the note as it was before.
|
|
|
|
**Remembering**
|
|
- Reminders, one-off or repeating, with Done and snooze from the card or the
|
|
notification.
|
|
- The desktop and Android apps notify you when the app isn't in front.
|
|
|
|
**Sharing and accounts**
|
|
- Share a note with a person or a group, to view or to edit.
|
|
- Invites, groups, per-account storage limits and an activity log for the admin.
|
|
- Password reset by email, or by a link the admin makes.
|
|
- Export everything as a zip, and import an Inkwell export or a Google Keep Takeout.
|
|
|
|
**Every device**
|
|
- Web app, installable as a PWA.
|
|
- Desktop app for Linux (`.deb`, Arch package, AppImage) and Windows. It keeps its
|
|
own local store, works with no server at all, and syncs once you link one. Install
|
|
it from your server's Account page, or with `curl -fsSL https://<your-server>/install.sh | sh`.
|
|
- Android app, downloaded from your server and updated by it.
|
|
|
|
## Troubleshooting
|
|
|
|
| What you see | Why | Fix |
|
|
|---|---|---|
|
|
| The app container restarts with a database error at startup | Postgres isn't up yet, or the two passwords differ | Wait a minute; check both `CHANGE_ME`s match |
|
|
| No "Install app" option in the browser | The page isn't on HTTPS | Serve it over HTTPS, or open it on `localhost` |
|
|
| The desktop or Android app can't reach a plain-HTTP server | A bare hostname is read as `https://` | Type the address with `http://` |
|
|
| A deployment upgraded from ThoughtSync shows no notes | It's pointed at new, empty volumes | Set `INKWELL_DB_VOLUME` and `INKWELL_DATA_VOLUME`; see [.env.example](.env.example) |
|
|
|
|
## Development
|
|
|
|
Backend (needs Postgres at `INKWELL_DATABASE_URL`):
|
|
|
|
```sh
|
|
pip install -e ".[dev]"
|
|
alembic upgrade head
|
|
hypercorn 'inkwell.app:create_app()' --bind 0.0.0.0:5000
|
|
```
|
|
|
|
Frontend, proxying `/api` to `:5000`: `cd frontend && npm install && npm run dev`
|
|
(http://localhost:5173). Or run everything with hot reload:
|
|
`docker compose -f docker-compose.dev.yml up`.
|
|
|
|
| Path | What's there |
|
|
|---|---|
|
|
| `src/inkwell/` | The Quart server |
|
|
| `alembic/` | Database migrations |
|
|
| `frontend/` | The Vue web app, also the desktop app's UI |
|
|
| `core/` | The Rust store and sync engine the desktop and Android apps share |
|
|
| `desktop/` | The Tauri desktop app and its packaging |
|
|
| `android/` | The Kotlin/Compose Android app |
|
|
|
|
How devices sync is in [docs/sync.md](docs/sync.md); how the Android app reaches a
|
|
server is in [docs/android-distribution.md](docs/android-distribution.md). Work
|
|
happens on `dev`; `main` is the stable line.
|
|
|
|
## Licence
|
|
|
|
Inkwell is free software under the [GNU Affero General Public License v3.0 only](LICENSE)
|
|
(`AGPL-3.0-only`). If you run a modified version for other people over a network, the
|
|
licence requires you to offer them its source.
|