-
-
Notifications
You must be signed in to change notification settings - Fork 162
Description
Hi @dullage,
First off, thank you for Flatnotes! The "folder of markdown files" philosophy is fantastic and exactly what many of us in the self-hosted / "Local-First" community are looking for.
I am opening this issue to share some friction points I encountered while packaging Flatnotes for NixOS. My goal is to suggest architectural tweaks that would make Flatnotes easier to package for distributions that prioritize immutable, reproducible builds (like NixOS, Guix, and others), which could eventually help it get into official package repositories (e.g., nixpkgs).
Currently, creating a native derivation is difficult because the project structure assumes a mutable, imperative install process (like Docker) where the application can modify itself at runtime.
The Pain Points
Here are the specific technical hurdles encountered when trying to build Flatnotes from source in a restricted, sandboxed environment:
1. Runtime Self-Modification (The Read-Only File System Issue)
This was the biggest blocker. The application currently attempts to rewrite its own source code at startup.
- Issue:
main.pycallsreplace_base_href(inhelpers.py), which attempts to openindex.htmlin write mode ("w") to inject thepath_prefix. - Impact: On secure systems or container setups where the application code is immutable (e.g.,
/nix/store/..., or a read-only Docker container), this causes the service to crash immediately withOSError: [Errno 30] Read-only file system. - Suggestion: Inject configuration variables (like
path_prefix) into the frontend at runtime using a non-destructive method—for example, injecting it into the HTML response in memory, or having the frontend fetch aconfig.jsonendpoint—rather than rewriting the static asset on disk.
2. Hardcoded Relative Paths
The Python server seems to assume the client/dist folder is relative to the process's Current Working Directory (os.getcwd()).
- Issue: When running as a system service, the Working Directory is often the data directory (e.g.,
/var/lib/flatnotes) to ensure saved notes go to the right place. However, the application code lives elsewhere (e.g.,/usr/share/flatnotesor/nix/store/...). This triggers aFileNotFoundErrorbecause the app looks forclient/distinside/var/lib/flatnotes. - Suggestion: Resolve static asset paths relative to the
__file__location of the running script, rather than the CWD. - Example:
BASE_DIR = Path(__file__).resolve().parent
3. The "Monorepo" Structure vs. Build Isolation
The project mixes the frontend (Node.js/Vite) and backend (Python/FastAPI) in a way that is hard to build separately.
- Issue: The frontend source is in
client/, butpackage.jsonandvite.config.jsare in the root. This forces the builder to download the entire repo (including python files) just to build the frontend assets, complicating dependency hashing and caching. - Suggestion: Moving frontend concerns (including
package.json) strictly inside theclient/directory would allow package managers to build the frontend as a distinct, isolated artifact before handing it to Python.
4. Binary Dependencies (sass-embedded)
The frontend build pulls in sass-embedded, which downloads a pre-compiled dart binary during npm install.
- Issue: On source-based distros, pre-compiled binaries often fail because they expect standard FHS paths (like
/lib64/ld-linux...) which may not exist. - Suggestion: This is largely an upstream issue with
sass, but providing a flag or documentation to use a pure-JS alternative for Sass compilation would improve portability.
Why this matters
Fixing these issues wouldn't just help NixOS users; it would make Flatnotes more robust and compliant with "Twelve-Factor App" principles. It would allow the application to run:
- From a strictly read-only container/filesystem (significant security benefit).
- With standard Linux directory structures (FHS compliant).
- Without needing Docker, reducing overhead for low-power devices.
I managed to get it working by applying several sed patches during the build to disable the file writing and fix paths, but having upstream support would be amazing.
Thanks again for the great tool!