A simple, self-hosted, encrypted notes application built with Flask.
- Secure: Note content is encrypted at rest.
- CRUD Operations: Create, view, edit, and delete notes through a clean web interface.
- Markdown Support: Notes are rendered from Markdown to HTML, with syntax highlighting for code blocks.
- Raw View: View the raw, unformatted text of any note.
- Share Notes: Make notes publicly viewable without authentication. Read only, no write access. Includes a share link.
- Authentication: Protected by simple HTTP Basic Authentication.
- Rate limiting per IP address
- CSRF protection for POST requests
- Configurable via environment variables
- Runs locally or in Docker
- Easy Setup: Automatically generates an encryption key on first run.
- Proxy Friendly: Designed to work behind a reverse proxy and correctly identify client IPs.
-
Clone the repository:
git clone https://github.com/teklynk/notes.git cd python_notes -
Create a virtual environment:
python3 -m venv venv source venv/bin/activate -
Install dependencies:
pip install -r requirements.txt
-
Configure environment variables:
- Rename
sample.envto.env - Edit
.envand set yourSECRET_KEY,ALLOWED_DOMAIN,HTTP_USER, andHTTP_PASS.
- Rename
-
Run the application:
python3 python_notes.py
-
Deactivate the virtual environment (optional):
deactivate
-
Configure environment variables:
- Rename
sample.docker-compose.ymltodocker-compose.yml. - Edit
docker-compose.ymland set yourSECRET_KEY,ALLOWED_DOMAIN,HTTP_USER,HTTP_PASS, andENCRYPTION_KEYunder theenvironmentsection.
- Rename
-
Build and run the container:
docker-compose up --build -d
- On first local run, the app will generate an
ENCRYPTION_KEYand save it to the.envfile if one does not already exist. - The
ENCRYPTION_KEYmust be a 32-byte, URL-safe, base64-encoded string. The app handles this for you, but it's good to know if you're setting it manually. - If using Docker, configure environment variables in
docker-compose.yml. The.envfile is only used for local development. - Authentication is optional. If
HTTP_USERandHTTP_PASSare not set, the application will be publicly accessible. - The app is designed to work behind a reverse proxy (e.g., Nginx, Cloudflare) and uses the
CF-Connecting-IPheader to identify the real client IP for rate limiting.

