Add reMarkable backup system with web UI

- Docker container with rmapi cloud backup, PDF conversion pipeline
- Web UI: file browser, multi-select, delete/move, thumbnail preview
- Sync: backup from reMarkable cloud, rmdoc→PDF conversion via rmc+Inkscape
- Excluded-files mechanism to prevent deleted items from returning after sync

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Borgal
2026-03-24 23:43:36 +01:00
parent 747a35e172
commit b63131c0c5
13 changed files with 1881 additions and 0 deletions

51
remarkable/Dockerfile Executable file
View File

@@ -0,0 +1,51 @@
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
rsync curl unzip python3 python3-pip \
inkscape poppler-utils cron \
php-cli \
&& rm -rf /var/lib/apt/lists/*
# rmc + Farb-Patch
RUN pip3 install "rmc==0.3.0" "rmscene>=0.7.0" "pypdf" "rmrl" --break-system-packages --ignore-installed packaging \
&& python3 - <<'EOF'
import pathlib
import rmc.exporters.writing_tools as m
f = pathlib.Path(m.__file__)
src = f.read_text()
src = src.replace(
"self.base_color = RM_PALETTE[base_color_id]",
"self.base_color = RM_PALETTE.get(base_color_id, (255, 235, 0) if base_color_id == 9 else (128, 128, 128))"
)
old = ' segment_color = [min(int(abs(intensity - 1) * 255), 60)] * 3\n return "rgb" + str(tuple(segment_color))'
new = ' r = min(int(self.base_color[0] * intensity), 255)\n g = min(int(self.base_color[1] * intensity), 255)\n b = min(int(self.base_color[2] * intensity), 255)\n return "rgb" + str((r, g, b))'
src = src.replace(old, new)
old_b = ' segment_color = [int(rev_intensity * (255 - self.base_color[0])),\n int(rev_intensity * (255 - self.base_color[1])),\n int(rev_intensity * (255 - self.base_color[2]))]\n return "rgb" + str(tuple(segment_color))'
new_b = ' segment_color = [int(255 - intensity * (255 - c)) for c in self.base_color]\n return "rgb" + str(tuple(segment_color))'
src = src.replace(old_b, new_b)
src = src.replace("self.base_opacity = 0.1", "self.base_opacity = 0.3")
f.write_text(src)
EOF
# rmapi binary
COPY backup/rmapi /usr/local/bin/rmapi
RUN chmod +x /usr/local/bin/rmapi
# Skripte
COPY scripts/backup-official-cloud.sh /usr/local/bin/remarkable-backup.sh
COPY scripts/convert-to-pdf.sh /usr/local/bin/remarkable-convert.sh
COPY scripts/merge-annotations.py /usr/local/bin/remarkable-merge.py
RUN chmod +x /usr/local/bin/remarkable-merge.py
RUN chmod +x /usr/local/bin/remarkable-backup.sh /usr/local/bin/remarkable-convert.sh
# Web-UI
COPY web/ /app/
# Entrypoint
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 8080
ENTRYPOINT ["/entrypoint.sh"]