An isolated build repository for generating .deb packages for Notolog Editor - a Python-powered Markdown editor featuring an integrated AI assistant, on-device LLM support, and optional file encryption.
▒█▄░▒█ ▒█▀▀▀▄ ▀▀█▀▀ ▒█▀▀▀▄ ▒█░░░ ▒█▀▀▀▄ ▒█▀▀█░
▒█▒█▒█ ▒█░░▒█ ░▒█░░ ▒█░░▒█ ▒█░░░ ▒█░░▒█ ▒█░░▄▄
▒█░░▀█ ▒█▄▄▄█ ░▒█░░ ▒█▄▄▄█ ▒█▄▄▄ ▒█▄▄▄█ ▒█▄▄▄█
This repo contains build scripts, CI/CD workflows, and Debian packaging files used to create and lint compliant .deb packages. It does not include application source code.
- 🌐 Official site: https://notolog.com
- 📚 Documentation: https://notolog.app
- 📦 Main app repo: https://github.com/notolog/notolog-editor
- 🛠️ This builder repo: https://github.com/notolog/notolog-debian
- ⚖️ License: MIT License
The easiest way to install Notolog on Ubuntu:
# Add the PPA repository
sudo add-apt-repository ppa:notolog/ppa
sudo apt update
# Install Notolog
sudo apt install notolog
# Run
notologSupported Ubuntu versions: Noble (24.04), Questing (25.10)
Note: This repository does not contain any third-party software. All third-party dependencies are bundled and attributed within the application package during the build process.
Essential packages required to perform the build:
sudo apt-get install build-essential debhelper lintianEssential Python packages:
pip install pyinstallerOptional system packages (install only if needed by your environment):
dh-autoreconf dh-exec g++ g++-12 libc6-dev libstdc++-12-dev libtool linux-libc-devThe date of the generated .deb file is derived from the changelog.
Remove any installed version of the package (e.g., notolog via pip) to avoid conflicts between the source and installed resources.
If both the local source appname (notolog/) and a pip-installed package appname (notolog) exist, PyInstaller may bundle the wrong version depending on the PYTHONPATH and Python's module resolution order.
- Local Source Directory: If
appnameis a local directory in your project root, PyInstaller will use the local source files, provided they are imported directly in the code. - Installed Package: If your environment resolves the
appnamemodule from site-packages, PyInstaller will bundle the installed version frompip.
Navigate to the pyinstaller/ directory and run one of the following commands:
cd pyinstaller
sudo ./build.sh
# or
bash build.shTo clean up cached data and perform linting, use the post-build.sh script located in the pyinstaller/ directory:
bash post-build.shThe built package can be installed with the command below.
sudo dpkg -i notolog_X.Y.Z_amd64.debIf the package was built on a local machine, the resulting .deb file is typically located in the parent directory (..) relative to where the debian/ directory resides.
Clean up .pyc files before building:
find . -name "*.pyc" -delete
find . -name "__pycache__" -deleteEnsure a clean PyInstaller environment:
pyinstaller --clean notolog-onefile.specRun the build with one of the following options:
pyinstaller notolog-onefile.specSet the app_root variable if building from within the pyinstaller/ directory. Leave it unset if building from the project root.
One-file build:
pyinstaller --onefile --noconfirm --name=notolog \
--collect-all=notolog notolog/app.py \
--add-data="notolog:notolog" \
--add-data="docs/*:docs" \
--add-data="CHANGELOG.md:." \
--add-data="CODE_OF_CONDUCT.md:." \
--add-data="CONTRIBUTING.md:." \
--add-data="LICENSE:." \
--add-data="README.md:." \
--add-data="SECURITY.md:." \
--add-data="ThirdPartyNotices.md:." \
--exclude-module __pycache__ \
--exclude-module "*.pyc" \
--exclude-module "*.pyo" \
--add-data="../venv/notolog/lib/python3.11/site-packages/emoji:emoji"One-dir build:
(Same as above, just replace --onefile with --onedir.)
The init script pyinstaller/runtime_hooks/init.py configures the app on first run based on user settings and package type. It verifies the current package type and adjusts settings accordingly.
Error importing numpy: you should not try to import numpy from its source directory
The issue may be caused by incompatible NumPy versions. Version 1.26.4 works fine, while versions 2.1.0 and later (e.g., 2.2.2) may result in errors. Check the version compatibility.
If you see:
qt.qpa.plugin: From 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platform plugin.
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: linuxfb, minimalegl, xcb, minimal, vkkhrdisplay, wayland, vnc, offscreen, wayland-egl, eglfs.
Aborted (core dumped)Install the required package:
sudo apt-get install libxcb-cursor0- REUSE https://reuse.software/faq/
- Bulk-license whole directories https://reuse.software/faq/#bulk-license
- Add copyright and licensing information to an uncommentable file https://reuse.software/faq/#uncommentable-file
- SPDX Licenses https://spdx.org/licenses/
- See
debian/copyrightfor a full SPDX-compatible license inventory.
Install REUSE
pip install reuseFetch missing licenses
# Download all SPDX-referenced licenses
reuse download --all
# Or download a specific license and place it in the LICENSES/ directory
reuse download PSF-2.0Run REUSE linting
reuse lintAnnotate specific files
reuse annotate --copyright="2024-2026 Author Name" \
--license="MIT" --skip-unrecognised \
debian/README.md debian/changelog debian/controlLint the built .deb package:
sudo apt-get install -y lintian
lintian notolog.debFor detailed output and to help debug any issues, use the --info flag:
lintian -i notolog.deb
# Or, for even more verbose output:
lintian -iIv notolog.debMake sure to follow the guidelines in debian/copyright:
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.
# Please avoid picking licenses with terms that are more restrictive than the
# packaged work, as it may make Debian's contributions unacceptable upstream.
#
# If you need, there are some extra license texts available in two places:
# /usr/share/debhelper/dh_make/licenses/
# /usr/share/common-licenses/
PIE (Position Independent Executable) hardening ensures that the binary can be loaded at a random memory address each time it runs.
This enhances security by enabling ASLR (Address Space Layout Randomization), which protects against memory corruption attacks like buffer overflows.
For .deb packages, this is a Debian security best practice and is checked by tools like lintian.
After building, run:
hardening-check pyinstaller/dist/notolog
# Or, if the app is already installed:
hardening-check /usr/bin/notologYou want to see:
Position Independent Executable: yes
Or, to check manually with readelf:
readelf -h /usr/bin/notolog | grep 'Type'Expected output:
Type: DYN (Position-Independent Executable)
Run this to validate:
desktop-file-validate /usr/share/applications/notolog.desktopdpkg-deb -c notolog_*.deb | grep 'man/man1'The output should be:
./usr/share/man/man1/notolog.1.gz
Then check the man entry:
man notologUse these steps to verify what's bundled into the PyInstaller binary - important for compliance, reproducibility, and Debian policy alignment.
Inspect .deb contents:
dpkg -c notolog.deb | grep '\.so'Find bundled shared objects in PyInstaller output:
find pyinstaller/dist/ -name "*.so*"If using a --onefile PyInstaller build, run the app once to trigger runtime extraction. Then inspect with:
ps aux | grep notolog
lsof -p $(pgrep notolog) | grep _MEI
# Or manually inspect the runtime directory:
find /usr/lib/notolog/runtime -type fOptional: Use strace if you need syscall-level info:
strace -f -e trace=openat /usr/bin/notologNote: strace is a syscall tracer. It works by launching (or attaching to) the process and intercepting all syscalls (like openat, read, etc.).
This means it will run the app while tracing - that's expected behavior.
See linked shared libraries:
ldd /usr/bin/notologCheck which Debian package provides a library:
dpkg -S libexpat.so.1
# or
apt show libexpat1
# and
cat /usr/share/doc/libexpat1/copyrightTo inspect the contents of a PyInstaller executable (ensure the virtual environment is activated):
pyi-archive_viewer pyinstaller/dist/notologInside the viewer shell:
> ls
> extract libexpat.so.1To confirm libllama.so and its dependencies are dynamically linked and runtime-bundled:
ldd /usr/lib/notolog/runtime/_MEI*/llama_cpp/lib/libllama.soTo verify bundled binaries for license metadata, use licensecheck:
licensecheck --shortname-scheme new --recursive /usr/lib/notolog/runtime/_MEIXXXX/Replace _MEIXXXX with the actual unpacked PyInstaller runtime path.
The --shortname-scheme new flag ensures SPDX-style identifiers (e.g. mit, lgpl-2.1+, etc.).
This is especially useful for auditing libraries bundled in --onefile PyInstaller builds.
Optional but Recommended. Add this to CI or locally:
pyi-archive_viewer pyinstaller/dist/notolog | tee archive-contents.txt
strings pyinstaller/dist/notolog | grep -iE 'key|token|user|secret|home|/Users|/home|__pycache__'This confirms no credentials, user paths, or environment variables leaked into the binary (e.g., from .env, dev configs, etc.).
For easier debugging and inspection, consider building with --onedir.
Note: onedir is not recommended for final Debian packaging, as it unpacks dozens of files and complicates reproducibility. Stick to --onefile for cleaner shipping.
The upstream metadata file should be located at debian/upstream/metadata. If using an example (metadata.ex), make sure to rename it to just metadata.
- See: https://wiki.debian.org/UpstreamMetadata for more information.
Example:
# User support or community link
Support: https://github.com/notolog/notolog-editor/discussionsThe build process is automated using GitHub Actions, and the resulting artifact is uploaded after the workflow completes.
Refer to .github/workflows/build.yaml for details and step-by-step instructions.
See CONTRIBUTING.md for guidelines.
This repository contains only build scripts and CI workflows. It does not include or redistribute any third-party software.
All third-party dependencies are pulled by the main application during build and bundled into the final .deb as part of the PyInstaller runtime. Licensing for each is tracked and included in the package metadata.
🦙 The CPU-only llama-cpp backend is built from source and dynamically links to:
libgompandlibstdc++: covered under the GPL with the GCC Runtime Library Exception, which permits linking from non-GPL software.- MIT-licensed internal
libggmlbackends (libggml.so,libggml-base.so,libggml-cpu.so).
This README.md file has been carefully crafted and edited using the Notolog Editor itself.