Stage two of PDF support: the file can now get in and out. No viewer yet — that is next. A PDF is an attachment like any other, so it inherits everything already built: encryption at rest, naming by content hash, deduplication, the orphan sweep, and the authenticated retrieval route the client already caches offline. The note points at it through notes.pdf_attachment_id. Raw request body rather than the base64 JSON images travel in. A scanned book is tens of megabytes and base64 adds a third to that, on a path that carries nothing but the file. The bytes are checked for %PDF- before anything is written, so the declared content type is never trusted. Images and PDFs are limited separately — INKNOTE_MAX_IMAGE_MB (25) and INKNOTE_MAX_PDF_MB (200) — because a 25 MB picture is nearly always a mistake and a 25 MB document is not. Both configurable; the limits exist so a runaway upload cannot fill the disk, not to ration anything. The JSON body limit now follows the image limit instead of being a second number that could drift away from it. Verified against a real PDF: uploaded, stored with the INKENC01 header, returned byte-identical, deduplicated on a second upload, a GIF renamed to .pdf refused with 415, unauthenticated refused with 401. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
34 lines
1.4 KiB
Bash
34 lines
1.4 KiB
Bash
# cp .env.example .env — Compose reads it from this directory.
|
|
# Back the finished .env up with the database: without ENCRYPTION_KEY the
|
|
# stored notes cannot be read again.
|
|
|
|
# Both: openssl rand -hex 32
|
|
JWT_SECRET=
|
|
ENCRYPTION_KEY=
|
|
|
|
# The first administrator. There is no public sign-up — every other account is
|
|
# created in the app under Account → Administration. Used only until an admin
|
|
# exists, then ignored, so they can never reset anything later.
|
|
INKNOTE_ADMIN_USER=
|
|
INKNOTE_ADMIN_PASSWORD=
|
|
|
|
# Where the notes are kept on the host. Defaults to /srv/inknote in production
|
|
# and ./data for development — leave it commented unless you want another path,
|
|
# since one .env serves both. Create the directory first, or Docker creates it
|
|
# as root and the server (uid 1000) cannot write:
|
|
# mkdir -p /srv/inknote/{db,uploads} && chown -R 1000:1000 /srv/inknote
|
|
# INKNOTE_DATA_DIR=/srv/inknote
|
|
#
|
|
# Under /root also run "chmod o+x /root", or the server cannot reach it at all.
|
|
# That and the alternative: readme.md → Where the data lives.
|
|
|
|
# ── Optional ── unset keeps the default shown
|
|
# INKNOTE_MAX_IMAGE_MB=25 # pasted images
|
|
# INKNOTE_MAX_PDF_MB=200 # imported PDFs, limited separately
|
|
# INKNOTE_UID=1000 # must own INKNOTE_DATA_DIR
|
|
# INKNOTE_GID=1000
|
|
# MAX_VERSIONS_PER_NOTE=50
|
|
# VERSION_RETENTION_DAYS=90
|
|
# VERSION_COALESCE_MINUTES=5
|
|
# ALLOWED_ORIGINS= # only if the UI is on another host
|