Up to now I had been self-hosting RSS with FreshRSS, but since Miniflux is lightweight and can integrate with all sorts of external services, I migrated to it.
I am building it with Docker again this time, and I am writing it up on the following assumptions.
Environment
- My own domain (already registered with Cloudflare)
- Network:
traefik-network(external) - CertResolver:
cloudflare - entryPoints:
web(80),websecure(443)
docker-compose.yml
services:
miniflux:
image: miniflux/miniflux:latest
container_name: miniflux
restart: always
depends_on:
db:
condition: service_healthy
environment:
- DATABASE_URL=postgres://miniflux:${DB_PASSWORD}@db/miniflux?sslmode=disable
- RUN_MIGRATIONS=1
- CREATE_ADMIN=1
- ADMIN_USERNAME=${ADMIN_USERNAME}
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- BASE_URL=https://${MINIFLUX_DOMAIN}
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-network"
- "traefik.http.routers.miniflux.rule=Host(`${MINIFLUX_DOMAIN}`)"
- "traefik.http.routers.miniflux.entrypoints=websecure"
- "traefik.http.routers.miniflux.tls=true"
- "traefik.http.routers.miniflux.tls.certresolver=cloudflare"
- "traefik.http.services.miniflux.loadbalancer.server.port=8080"
networks:
- traefik-network
- miniflux-internal
healthcheck:
test: ["CMD", "/usr/bin/miniflux", "-healthcheck", "auto"]
interval: 10s
start_period: 30s
db:
image: postgres:17
container_name: miniflux-db
restart: always
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=miniflux
volumes:
- miniflux-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "miniflux"]
interval: 10s
start_period: 30s
networks:
- miniflux-internal
networks:
traefik-network:
external: true
miniflux-internal:
driver: bridge
volumes:
miniflux-db:.env
DB_PASSWORD=your_secure_db_password
ADMIN_USERNAME=admin
ADMIN_PASSWORD=your_secure_admin_password
MINIFLUX_DOMAIN=rss.your-domain.comStarting it up
docker compose up -dBuilding Miniflux safely with Traefik + Docker Compose
- PostgreSQL: the official documentation uses Postgres 18, but it is still beta, so I use 17
- Network isolation: the DB is connected only to
miniflux-internal, so it cannot be reached from outside - Traefik integration: the miniflux container is connected to
traefik-network, and the routing is configured with labels - Ports: miniflux starts on 8080 by default, so there is no need to publish a port to the host (Traefik handles it)