# Poznote: a self-hosted notes and wiki app you run with Docker Compose

> Poznote is a PHP note-taking application distributed as a Docker image, with an MCP server for AI clients and optional S3, Git and webhook integrations. It installs cleanly, but the README outsources most feature detail to its own website.

**timothepoznanski/poznote** — Powerful note-taking without the hassle.

- Repository: https://github.com/timothepoznanski/poznote
- Website: https://poznote.com
- Stars: 882 · Forks: 37
- Language: PHP
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/timothepoznanski-poznote

## What Poznote is, and who ends up running it

Poznote is a note-taking web application written in PHP, published under the MIT licence, and described in its own README as "a free, self-hosted, open-source alternative to Notion, Obsidian, Evernote, or OneNote." The repository topics list docker, self-hosted, notes, tasks, todolist, wiki and documentation, which is a fair summary of the intended scope: notes that can also serve as a small internal wiki, with to-do items in the same place.

The audience is narrower than the tagline suggests. Obsidian is a local-first desktop editor with a plugin ecosystem; Poznote is a server application you reach through a browser. Anyone who wants their notes to keep working on a laptop with no network and no container running is looking at the wrong tool. The people who get value here are those who already run a home server or a small VPS, want a shared space for notes and tasks, and would rather manage one Compose file than pay a subscription per seat. The README also points at a hosted option at poznote.com/hosting.html for people who do not want to run a server at all, which is a reasonable admission that self-hosting is the real cost of entry.

## The Docker Compose topology: two containers, one SQLite file

The repository ships a docker-compose.yml that defines two services. The webserver service pulls ghcr.io/timothepoznanski/poznote:6 and sets SQLITE_DATABASE to /var/www/html/data/database/poznote.db. That path is inside a bind mount: ./data on the host maps to /var/www/html/data in the container. Everything persistent, including the database and presumably attachments, lives under that one directory. Backing up Poznote is therefore a file copy operation, and so is destroying it.

The second service is mcp-server, pulling ghcr.io/timothepoznanski/poznote-mcp:6. It points at the webserver through POZNOTE_API_URL: http://webserver:80/api/v1 and mounts the same ./data directory read-only. Its port binding is deliberately local: 127.0.0.1:${POZNOTE_MCP_PORT:-8045}:8045, so the MCP endpoint is not exposed to the network by default. It also depends_on the webserver, which means Compose starts them in order but does not wait for the health check to pass before starting the MCP container.

The webserver has a healthcheck that runs wget against http://127.0.0.1/api/health every 30 seconds with 3 retries and a 10 second start period. Two environment variables tune resource behaviour and both default to empty, meaning the image values apply: POZNOTE_PHP_FPM_MAX_CHILDREN (image default 10, per docker/php-fpm/www.conf) and POZNOTE_PHP_MEMORY_LIMIT in MB (image default 512, per docker/php/php.ini). The Dockerfile is a multi-stage build on php:8.4-fpm-alpine3.23 that installs nginx, supervisor and the pdo, pdo_sqlite, zip, curl and opcache extensions. A second target named rootless runs the whole container as uid/gid 1000 with nginx on port 8080, for Kubernetes restricted PodSecurityStandard, docker run --user or rootless Podman.

## Installing Poznote with Docker Compose on Linux

The README gives per-platform instructions for Windows, Linux and macOS that differ only in the shell. The Linux path assumes Docker Engine and the Compose plugin are already installed. Create a directory, pull the two template files from the main branch, edit the environment file, then pull and start.

```bash
mkdir poznote
cd poznote
curl -o .env https://raw.githubusercontent.com/timothepoznanski/poznote/main/.env.template
vi .env
curl -o docker-compose.yml https://raw.githubusercontent.com/timothepoznanski/poznote/main/docker-compose.yml
docker compose pull
docker compose up -d
```

The .env file is where HTTP_WEB_PORT comes from, since the Compose file maps "${HTTP_WEB_PORT}:80". The README does not print the contents of .env.template, so read the downloaded file before starting the stack rather than assuming a default port. The Windows instructions use the same sequence with mkdir, cd, curl, notepad and docker compose, so the only real difference is the editor.

Once the containers are up, the README's Access section is where you find the URL, and the demo instance at demo.poznote.com accepts the login poznote with password poznote. That demo is the fastest way to see the editor, the note types and the snapshots feature before you commit a server to it. For Kubernetes there is a community Helm chart: helm repo add helmforge https://repo.helmforge.dev, then helm repo update, then helm install poznote helmforge/poznote --namespace poznote --create-namespace. The README states that chart is maintained by the HelmForge community rather than by the project, which matters when you are deciding who to file a bug with.

## Updates, snapshots and the upgrade path the README insists on

The Compose file carries a comment in capitals: when updating Poznote, always follow the instructions at the project's update section. That is a signal worth taking seriously, because the image tag is ghcr.io/timothepoznanski/poznote:6, a major-version tag rather than a pinned patch. Pulling again can move you across minor releases without an explicit version change in your Compose file. The recent release history shows why that matters: 6.82.0, 6.83.0 and 6.84.0 all landed within roughly two days of each other in September 2026, so the project ships often and a floating major tag will pick those up.

Snapshots are a first-class feature in the table of contents, which suggests the application keeps its own point-in-time copies of notes. The README does not describe the snapshot retention policy or where snapshots are stored, so treat that as something to check in the interface rather than something you can plan storage for from the documentation. The same caution applies to the SQLite choice: the Compose file hardcodes a single database file, and nothing in the README describes migrating to PostgreSQL or MySQL. If your note volume or concurrent editor count grows past what one SQLite file and a PHP-FPM pool of 10 children can serve, the documented escape hatch is not there. POZNOTE_PHP_FPM_MAX_CHILDREN exists, so you can raise concurrency, but raising it does not change the storage engine underneath.

## The MCP server, AI assistant and API surface

Poznote is unusual among self-hosted note apps in shipping an MCP server as a supported component rather than a third-party add-on. The mcp-server container talks to the webserver over the internal network at http://webserver:80/api/v1, and the Compose file exposes three settings for it: POZNOTE_DEBUG (default false), POZNOTE_USER_ID (default 1) and POZNOTE_MCP_AUTH_TOKEN (default empty). The default user ID of 1 is worth noticing. If you run a multi-user instance, the MCP container is configured to act as user 1 unless you change that variable, and the README does not spell out what that means for note ownership.

The MCP port binding to 127.0.0.1 is the right default, since an MCP endpoint that can read and write notes is not something to expose on a public interface. Setting POZNOTE_MCP_AUTH_TOKEN to an empty value is also the default, so the authentication story for the MCP endpoint depends on that loopback binding rather than on a token unless you configure one. The repository also contains a Chrome extension directory and a poznote-url-saver directory, plus README sections for share-to-Poznote on Android and an API documentation page. None of those are described in enough detail in the README to say how they authenticate or what they can reach.

## Where Poznote is the wrong choice

The README's own feature list is a link. "Discover all the features here" points at poznote.com, and the screenshots section does the same. That is a documentation trade-off, not a bug, but it means you cannot evaluate the feature set from the repository alone, and you cannot diff features between releases from the release notes either, which are titled simply "Release 6.84.0" and so on.

The harder limitation is operational. A single SQLite file behind a bind mount is simple until it is not: concurrent writers, a corrupted file, or a host disk failure all hit the same artifact, and the README does not document a rollback procedure for a failed upgrade. There is a Backup/Export and a Restore/Import section, and there are S3 backups and Git synchronization sections, so the mechanisms exist, but the README does not state what a backup contains or whether restoring across a major version is supported. If your requirement is a notes system with a formal, tested restore path and a documented schema, this is not it. If your requirement is a personal or small-team wiki that you can snapshot by copying a directory, it fits.

## How it compares with running a plain wiki or a local-first editor

The obvious alternative for the same job is a wiki engine such as Wiki.js or DokuWiki, or a general-purpose self-hosted app platform where you install a notes container. Those differ from Poznote in architecture rather than in features: a wiki engine typically stores pages as files or in a relational database you choose, and it usually separates the rendering engine from the storage layer. Poznote does the opposite. It bundles nginx, PHP-FPM, supervisord and a reminder-email worker into one image and pins the storage to SQLite at a fixed path. You get fewer decisions to make and fewer ways to tune the deployment.

The other comparison is the local-first editor, which the README names directly by positioning Poznote against Obsidian and OneNote. The difference is where the source of truth lives. A local-first editor keeps files on your machine and syncs them; Poznote keeps them in a database on a server and you reach them over HTTP. That makes Poznote better for sharing and worse for working on a plane. It also changes what a backup is: a folder of Markdown files versus a SQLite database, and the README does not say whether notes can be exported back out as plain files.

## Conclusion

Adopt Poznote if you want a Notion-style notes and wiki app on your own hardware and you are comfortable with Docker Compose and a SQLite file in ./data. Skip it if you need per-user encryption, a documented migration path away from SQLite, or a feature matrix you can read without leaving the repository. Before committing, open the live demo at demo.poznote.com with the credentials poznote/poznote, then check that the .env.template keys match the variables your deployment actually needs.

## FAQ

### How do I install Poznote?

The README's Linux, macOS and Windows instructions all use Docker Compose: create a directory, download .env.template and docker-compose.yml from the main branch, edit the .env file, then run docker compose pull and docker compose up -d. Windows and macOS require Docker Desktop first; Linux requires Docker Engine and the Compose plugin.

### Does Poznote need a separate database server?

No. The Compose file sets SQLITE_DATABASE to /var/www/html/data/database/poznote.db and mounts the host's ./data directory at /var/www/html/data, so the database is a single file inside that bind mount. The README does not describe a supported migration to another database engine.

### Can I try Poznote before installing it?

Yes. The README lists a live demo at demo.poznote.com with the login poznote and the password poznote. It is the quickest way to see the editor and features that the README otherwise links out to poznote.com.

### What is the MCP server in Poznote for?

The docker-compose.yml runs a second container, ghcr.io/timothepoznanski/poznote-mcp:6, which talks to the webserver at http://webserver:80/api/v1 and is bound to 127.0.0.1 on port 8045 by default. It is configured with POZNOTE_USER_ID defaulting to 1 and an empty POZNOTE_MCP_AUTH_TOKEN by default.

## Sources

- [License: MIT](https://github.com/timothepoznanski/poznote/blob/main/LICENSE)
- [Project website](https://poznote.com)
- [README](https://github.com/timothepoznanski/poznote/blob/main/README.md)
- [Releases](https://github.com/timothepoznanski/poznote/releases)
- [timothepoznanski/poznote on GitHub](https://github.com/timothepoznanski/poznote)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/timothepoznanski-poznote
