mirror of
https://github.com/R0m1k3/FlowReader.git
synced 2026-10-18 12:48:07 +02:00
feat: rewrite the backend in Rust
Replaces the Go server with a Rust one (axum, tokio, sqlx, feed-rs, ammonia, reqwest) serving the same REST/WebSocket API, so the React frontend is unchanged. - Same database: migrations keep the schema_migrations table and file names, Argon2id hashes and hashed session tokens created by the Go server keep working (users stay logged in), and feed item GUIDs are computed the same way, so existing articles are not re-ingested. - Same security model: SSRF-safe fetching (public addresses only, checked at resolution time and on every redirect), HTML sanitization, CSP and security headers, same-origin guard, WebSocket origin check, per-IP / per-user rate limits, trusted-proxy aware client IPs. - Fix: articles whose publication date lies in the future (ingested before the clamp existed) pinned the top of the list. The maintenance job now pulls such dates back at startup and daily. - Relative links and images in feed content are resolved against the article URL instead of being dropped. - Deploy: static musl binary in an Alpine image; the Unraid compose file uses pull_policy: always so the new image is applied on the next `docker compose up -d`. CI runs fmt, clippy and tests (including a PostgreSQL integration test) before building the image. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fc1UFpB4V1MGWLxHAu3BMK
This commit is contained in:
70 files changed
+8127
-5283
No files matched your search
+15
-9
@@ -1,6 +1,6 @@
|
||||
# Multi-stage Dockerfile for FlowReader
|
||||
|
||||
# Step 1: Build the React Frontend
|
||||
# Step 1: Build the React frontend
|
||||
FROM node:22-alpine AS web-builder
|
||||
WORKDIR /app/web
|
||||
COPY web/package*.json ./
|
||||
@@ -9,16 +9,20 @@ RUN npm ci --no-audit --no-fund
|
||||
COPY web/ ./
|
||||
RUN npm run build
|
||||
|
||||
# Step 2: Build the Go Backend
|
||||
FROM golang:1.26-alpine AS builder
|
||||
# Step 2: Build the Rust backend (static musl binary)
|
||||
FROM rust:1-alpine AS builder
|
||||
RUN apk add --no-cache musl-dev gcc
|
||||
WORKDIR /app
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download && go mod verify
|
||||
COPY cmd/ ./cmd/
|
||||
COPY internal/ ./internal/
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-w -s" -o /server ./cmd/server
|
||||
# Dependencies first, so they stay cached while only src/ changes
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
RUN mkdir src && echo 'fn main() {}' > src/main.rs \
|
||||
&& cargo build --release --locked \
|
||||
&& rm -rf src target/release/.fingerprint/flowreader-* target/release/deps/flowreader-*
|
||||
COPY src ./src
|
||||
# touch: the copied sources may be older than the placeholder build
|
||||
RUN touch src/main.rs && cargo build --release --locked && cp target/release/flowreader /server
|
||||
|
||||
# Step 3: Final Production Image
|
||||
# Step 3: Final production image
|
||||
FROM alpine:3.22
|
||||
WORKDIR /app
|
||||
RUN apk add --no-cache wget ca-certificates tzdata \
|
||||
@@ -30,4 +34,6 @@ COPY migrations /app/migrations
|
||||
|
||||
USER flowreader
|
||||
EXPOSE 8080
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD wget -q --spider http://localhost:8080/health || exit 1
|
||||
CMD ["/app/server"]
|
||||
Reference in new issue
Block a user