News Sources
News Sources
Information
News Sources is a self-hosted news aggregation service. It runs as a small stack of three containers — a PostgreSQL database, a backend API, and a frontend web UI — and is exposed through Traefik behind Authentik SSO.
- A Postgres database (
news-db) persists the aggregated sources and articles. - A backend API serves the data on
${BACKEND_PORT}and connects to Postgres viaDATABASE_URL. - A frontend web UI is routed through Traefik at
${NEWS_FRONTEND_CONTAINER_NAME}.${PROJECT_HOSTNAME}and protected by Authentik. - A seed
init.sqlis mounted into the Postgres entrypoint to initialize the schema on first boot.
- Just News Sources Commands
| Type | Command |
|---|---|
| Start | docker compose up news-sources -d |
| Shutdown | docker compose down news-sources |
- Once started, the frontend should be hit from this url:
| URL | |
|---|---|
| Non-SSL (Web UI) | http://localhost:${NEWS_FRONTEND_PORT:-8082} |
| Image | lquincarter/news-sources-backend, lquincarter/news-sources-frontend |
The frontend is published through Traefik, so in normal operation you reach it at
https://${NEWS_FRONTEND_CONTAINER_NAME}.${PROJECT_HOSTNAME}rather than the raw host port. The backend port (${BACKEND_PORT}) is for API/client use.
News Sources Example Docker Compose
services:
db:
image: postgres:16-alpine
container_name: news-db
env_file:
- ./.env
- ../../.env
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "${DB_PORT}:5432"
volumes:
- ${DEFAULT_CONTAINER_DATA_LOCATION}/NewsSources/pgdata:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
profiles:
- all
- news
networks:
- news
backend:
image: lquincarter/news-sources-backend:0.0.1
container_name: news-backend
ports:
- "${BACKEND_PORT}:3000"
env_file:
- ./.env
- ../../.env
environment:
PORT: 3000
DATABASE_URL: ${DATABASE_URL}
depends_on:
db:
condition: service_healthy
restart: unless-stopped
profiles:
- all
- news
networks:
- homelab
- news
frontend:
image: lquincarter/news-sources-frontend:0.0.1
container_name: ${NEWS_FRONTEND_CONTAINER_NAME}
env_file:
- ./.env
- ../../.env
ports:
- "${NEWS_FRONTEND_PORT}:80"
labels:
- "traefik.enable=true"
- "traefik.http.routers.${NEWS_FRONTEND_CONTAINER_NAME}.rule=Host(`${NEWS_FRONTEND_CONTAINER_NAME}.${PROJECT_HOSTNAME}`)"
- "traefik.http.routers.${NEWS_FRONTEND_CONTAINER_NAME}.entrypoints=https"
- "traefik.http.routers.${NEWS_FRONTEND_CONTAINER_NAME}.tls=true"
- "traefik.http.routers.${NEWS_FRONTEND_CONTAINER_NAME}.priority=10"
- ${NEWS_FRONTEND_AUTHENTIK_MIDDLEWARE:-}
restart: unless-stopped
profiles:
- all
- news
networks:
- homelab
News Sources Example .env file
## News Sources
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres_secure_password #CHANGE_ME
POSTGRES_DB=news_sources
DB_HOST=db
DB_PORT=5432
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${DB_HOST}:${DB_PORT}/${POSTGRES_DB}
NEWS_FRONTEND_PORT=8082
BACKEND_PORT=3000
NEWS_FRONTEND_CONTAINER_NAME=news-frontend
Heads Up!
- The
backendservice waits fordbto be healthy (depends_on: db: condition: service_healthy) before starting. Make sure the Postgres credentials in.envmatch what the backend expects viaDATABASE_URL. - The
init.sqlseed file is mounted read-only into the Postgres entrypoint and only runs on a fresh database volume. - Leave the
NEWS_FRONTEND_AUTHENTIK_MIDDLEWAREline as-is so the frontend is protected by Authentik SSO when configured.