mirror of
https://github.com/R0m1k3/FlowReader.git
synced 2026-10-11 17:28:05 +02:00
chore(deploy): non-root image, reproducible builds, private database
- Dockerfile: Go 1.26, npm ci, go mod verify, non-root user, alpine 3.22. - Compose: Postgres no longer published on the host, password and new security settings read from .env, GOMEMLIMIT. - README: document new environment variables and reading shortcuts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
360f3cf012
commit
9eaed0aea4
5 files changed
+72
-27
No files matched your search
+4
-2
@@ -26,14 +26,16 @@
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
task.md
|
task.md
|
||||||
|
|
||||||
# Go
|
# Go (go.sum is committed for reproducible, verified builds)
|
||||||
vendor/
|
vendor/
|
||||||
go.sum
|
|
||||||
|
|
||||||
# Node
|
# Node
|
||||||
node_modules/
|
node_modules/
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
|
||||||
|
# Tooling
|
||||||
|
.playwright-mcp/
|
||||||
|
|
||||||
# FlowReader Specific
|
# FlowReader Specific
|
||||||
/_bmad-output/tmp/
|
/_bmad-output/tmp/
|
||||||
+16
-15
@@ -1,32 +1,33 @@
|
|||||||
# Multi-stage Dockerfile for FlowReader
|
# Multi-stage Dockerfile for FlowReader
|
||||||
|
|
||||||
# Step 1: Build the React Frontend
|
# Step 1: Build the React Frontend
|
||||||
FROM node:20-alpine AS web-builder
|
FROM node:22-alpine AS web-builder
|
||||||
WORKDIR /app/web
|
WORKDIR /app/web
|
||||||
COPY web/package*.json ./
|
COPY web/package*.json ./
|
||||||
RUN npm install
|
# Reproducible install from the lockfile
|
||||||
|
RUN npm ci --no-audit --no-fund
|
||||||
COPY web/ ./
|
COPY web/ ./
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Step 2: Build the Go Backend
|
# Step 2: Build the Go Backend
|
||||||
FROM golang:1.24-alpine AS builder
|
FROM golang:1.26-alpine AS builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY . .
|
COPY go.mod go.sum ./
|
||||||
RUN go mod tidy
|
RUN go mod download && go mod verify
|
||||||
RUN go mod download
|
COPY cmd/ ./cmd/
|
||||||
# Copy the built frontend from Step 1
|
COPY internal/ ./internal/
|
||||||
COPY --from=web-builder /app/web/dist ./web/dist
|
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-w -s" -o /server ./cmd/server
|
||||||
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /server ./cmd/server
|
|
||||||
|
|
||||||
# Step 3: Final Production Image
|
# Step 3: Final Production Image
|
||||||
FROM alpine:3.19
|
FROM alpine:3.22
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN apk add --no-cache wget ca-certificates
|
RUN apk add --no-cache wget ca-certificates tzdata \
|
||||||
|
&& adduser -D -H -u 10001 flowreader
|
||||||
COPY --from=builder /server /app/server
|
COPY --from=builder /server /app/server
|
||||||
# Copy the static files for the Go server to serve
|
# Static frontend and migrations (read-only for the app user)
|
||||||
COPY --from=builder /app/web/dist /app/web/dist
|
COPY --from=web-builder /app/web/dist /app/web/dist
|
||||||
# Copy migration files for auto-migration
|
COPY migrations /app/migrations
|
||||||
COPY --from=builder /app/migrations /app/migrations
|
|
||||||
|
|
||||||
|
USER flowreader
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
CMD ["/app/server"]
|
CMD ["/app/server"]
|
||||||
@@ -87,13 +87,30 @@ Un template dédié est fourni pour les utilisateurs d'Unraid.
|
|||||||
| `PORT` | Port du serveur | `8080` |
|
| `PORT` | Port du serveur | `8080` |
|
||||||
| `DATABASE_URL` | Connexion PostgreSQL | `postgres://...` |
|
| `DATABASE_URL` | Connexion PostgreSQL | `postgres://...` |
|
||||||
| `OPENROUTER_API_KEY` | Clé pour les résumés IA | *(Optionnel)* |
|
| `OPENROUTER_API_KEY` | Clé pour les résumés IA | *(Optionnel)* |
|
||||||
|
| `OPENROUTER_MODEL` | Modèle utilisé pour les résumés | `google/gemini-2.0-flash-001` |
|
||||||
|
| `POSTGRES_PASSWORD` | Mot de passe PostgreSQL (compose, à mettre dans `.env`) | `flowreader` — **à changer** |
|
||||||
|
| `REGISTRATION_ENABLED` | `false` pour fermer les inscriptions (le 1er compte, admin, reste possible) | `true` |
|
||||||
|
| `TRUSTED_PROXIES` | IP/CIDR du reverse proxy (ex. `172.16.0.0/12`) pour le rate-limit par IP client | *(vide)* |
|
||||||
|
| `COOKIE_SECURE` | Forcer le cookie `Secure` (HTTPS derrière proxy) | auto |
|
||||||
|
| `WS_ALLOWED_ORIGINS` | Origines WebSocket supplémentaires | *(vide)* |
|
||||||
|
|
||||||
|
> 🔒 La base PostgreSQL n'est plus exposée sur l'hôte par défaut. Changez `POSTGRES_PASSWORD`
|
||||||
|
> **avant** le premier démarrage (il n'est appliqué qu'à la création du volume).
|
||||||
|
|
||||||
|
### Lecture
|
||||||
|
|
||||||
|
- Raccourcis clavier : `j`/`k` naviguer, `o` ouvrir, `m` lu/non lu, `s` favori, `v` original,
|
||||||
|
`/` rechercher, `u` non lus/tous, `r` actualiser, `Espace` page suivante puis article suivant,
|
||||||
|
`?` aide.
|
||||||
|
- Bouton **Aa** dans le lecteur : thème (clair, sépia, sombre, auto), police (serif, sans,
|
||||||
|
Atkinson Hyperlegible), taille, interligne et largeur de colonne.
|
||||||
|
|
||||||
## 🛠️ Développement
|
## 🛠️ Développement
|
||||||
|
|
||||||
Envie de mettre les mains dans le code ?
|
Envie de mettre les mains dans le code ?
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Pré-requis : Go 1.22+, Node 20+, Docker
|
# Pré-requis : Go 1.26+, Node 22+, Docker
|
||||||
|
|
||||||
# 1. Lancer les services (DB)
|
# 1. Lancer les services (DB)
|
||||||
make docker-up
|
make docker-up
|
||||||
|
|||||||
@@ -10,8 +10,19 @@ services:
|
|||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
environment:
|
environment:
|
||||||
- PORT=8080
|
- PORT=8080
|
||||||
- DATABASE_URL=postgres://flowreader:flowreader@db:5432/flowreader?sslmode=disable
|
# Set a strong password in a .env file next to this compose file.
|
||||||
- OPENROUTER_API_KEY=votre_clef_ici
|
# Note: POSTGRES_PASSWORD only applies when the volume is first created.
|
||||||
|
- DATABASE_URL=postgres://flowreader:${POSTGRES_PASSWORD:-flowreader}@db:5432/flowreader?sslmode=disable
|
||||||
|
# Close public sign-ups once your account exists (the first account is admin).
|
||||||
|
- REGISTRATION_ENABLED=${REGISTRATION_ENABLED:-true}
|
||||||
|
# Behind a reverse proxy (Traefik, NPM, Caddy…): its IP/CIDR, so rate
|
||||||
|
# limiting sees real client IPs. Leave empty when exposed directly.
|
||||||
|
- TRUSTED_PROXIES=${TRUSTED_PROXIES:-}
|
||||||
|
# Force Secure cookies when served over HTTPS behind a proxy.
|
||||||
|
- COOKIE_SECURE=${COOKIE_SECURE:-}
|
||||||
|
- GOMEMLIMIT=48MiB
|
||||||
|
# Optional: AI summaries (OpenRouter). Leave empty to disable.
|
||||||
|
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -25,13 +36,15 @@ services:
|
|||||||
container_name: flowreader-db
|
container_name: flowreader-db
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_USER=flowreader
|
- POSTGRES_USER=flowreader
|
||||||
- POSTGRES_PASSWORD=flowreader
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-flowreader}
|
||||||
- POSTGRES_DB=flowreader
|
- POSTGRES_DB=flowreader
|
||||||
volumes:
|
volumes:
|
||||||
# Persistance des données sur Unraid (chemin typique)
|
# Persistance des données sur Unraid (chemin typique)
|
||||||
- /mnt/user/appdata/flowreader/postgres_data:/var/lib/postgresql/data
|
- /mnt/user/appdata/flowreader/postgres_data:/var/lib/postgresql/data
|
||||||
ports:
|
# Not published on the host: only the app container needs the database.
|
||||||
- "5432:5432"
|
# Uncomment for local debugging only (and bind to 127.0.0.1).
|
||||||
|
# ports:
|
||||||
|
# - "127.0.0.1:5432:5432"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: [ "CMD-SHELL", "pg_isready -U flowreader -d flowreader" ]
|
test: [ "CMD-SHELL", "pg_isready -U flowreader -d flowreader" ]
|
||||||
|
|||||||
+16
-4
@@ -7,7 +7,17 @@ services:
|
|||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
environment:
|
environment:
|
||||||
- PORT=8080
|
- PORT=8080
|
||||||
- DATABASE_URL=postgres://flowreader:flowreader@db:5432/flowreader?sslmode=disable
|
# Set a strong password in a .env file next to this compose file.
|
||||||
|
# Note: POSTGRES_PASSWORD only applies when the volume is first created.
|
||||||
|
- DATABASE_URL=postgres://flowreader:${POSTGRES_PASSWORD:-flowreader}@db:5432/flowreader?sslmode=disable
|
||||||
|
# Close public sign-ups once your account exists (the first account is admin).
|
||||||
|
- REGISTRATION_ENABLED=${REGISTRATION_ENABLED:-true}
|
||||||
|
# Behind a reverse proxy (Traefik, NPM, Caddy…): its IP/CIDR, so rate
|
||||||
|
# limiting sees real client IPs. Leave empty when exposed directly.
|
||||||
|
- TRUSTED_PROXIES=${TRUSTED_PROXIES:-}
|
||||||
|
# Force Secure cookies when served over HTTPS behind a proxy.
|
||||||
|
- COOKIE_SECURE=${COOKIE_SECURE:-}
|
||||||
|
- GOMEMLIMIT=48MiB
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -27,12 +37,14 @@ services:
|
|||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_USER=flowreader
|
- POSTGRES_USER=flowreader
|
||||||
- POSTGRES_PASSWORD=flowreader
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-flowreader}
|
||||||
- POSTGRES_DB=flowreader
|
- POSTGRES_DB=flowreader
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
ports:
|
# Not published on the host: only the app container needs the database.
|
||||||
- "5432:5432"
|
# Uncomment for local debugging only (and bind to 127.0.0.1).
|
||||||
|
# ports:
|
||||||
|
# - "127.0.0.1:5432:5432"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: [ "CMD-SHELL", "pg_isready -U flowreader -d flowreader" ]
|
test: [ "CMD-SHELL", "pg_isready -U flowreader -d flowreader" ]
|
||||||
|
|||||||
Reference in new issue
Block a user