68 lines
2.6 KiB
Markdown
68 lines
2.6 KiB
Markdown
|
|
# Subfeed
|
||
|
|
|
||
|
|
Self-hosted, multi-user web app for browsing **your own YouTube subscriptions** the way you
|
||
|
|
actually want: precise filtering and sorting (by language, topic, length, age, watch state…),
|
||
|
|
a fast local-first feed, and one-click playback that opens the real youtube.com — so your
|
||
|
|
browser's ad blocking and SponsorBlock keep working exactly as before.
|
||
|
|
|
||
|
|
Each user signs in with their own Google account (invite-only) and sees only their own
|
||
|
|
subscriptions. All the expensive data (channels, videos, metadata) is fetched from YouTube
|
||
|
|
once and stored locally, so filtering/searching/sorting are instant and don't burn API quota.
|
||
|
|
|
||
|
|
> Status: early development. Milestone **M1** (foundation) is in place: docker-compose stack,
|
||
|
|
> FastAPI backend, Google OAuth login with an email invite-list, and encrypted token storage.
|
||
|
|
|
||
|
|
## Requirements
|
||
|
|
|
||
|
|
- Docker + Docker Compose
|
||
|
|
- A Google Cloud project with an OAuth client (see below)
|
||
|
|
|
||
|
|
## Quick start
|
||
|
|
|
||
|
|
1. Copy the env template and generate secrets:
|
||
|
|
|
||
|
|
```sh
|
||
|
|
cp .env.example .env
|
||
|
|
python -c "import secrets;print('SECRET_KEY=',secrets.token_urlsafe(48))"
|
||
|
|
python -c "import base64,os;print('TOKEN_ENCRYPTION_KEY=',base64.urlsafe_b64encode(os.urandom(32)).decode())"
|
||
|
|
```
|
||
|
|
|
||
|
|
Paste the generated values into `.env`.
|
||
|
|
|
||
|
|
2. Create a Google OAuth client (Google Cloud Console → APIs & Services):
|
||
|
|
- Enable the **YouTube Data API v3**.
|
||
|
|
- OAuth consent screen: **External**, publishing status **Testing**, and add every invited
|
||
|
|
Google account as a **Test user** (up to 100 — no app verification needed at this scale).
|
||
|
|
- Create credentials → **OAuth client ID** → type **Web application**.
|
||
|
|
- Authorized redirect URI: `http://localhost:8080/auth/callback`
|
||
|
|
(must match `OAUTH_REDIRECT_URL` in `.env`).
|
||
|
|
- Put the client ID/secret into `.env`, and list invited emails in `ALLOWED_EMAILS`.
|
||
|
|
|
||
|
|
3. Start it:
|
||
|
|
|
||
|
|
```sh
|
||
|
|
docker compose up --build
|
||
|
|
```
|
||
|
|
|
||
|
|
Open http://localhost:8080 and sign in. Database migrations run automatically on startup.
|
||
|
|
|
||
|
|
## Backup & moving to another machine
|
||
|
|
|
||
|
|
All data lives in the `pgdata` Postgres volume — moving to another host (e.g. a Proxmox Linux
|
||
|
|
server) does **not** require re-fetching from YouTube. Copy your `.env` (keep the same
|
||
|
|
`TOKEN_ENCRYPTION_KEY` and Google client so stored tokens stay valid), then:
|
||
|
|
|
||
|
|
```sh
|
||
|
|
./scripts/backup.sh # -> backups/subfeed-<timestamp>.dump (Windows: scripts\backup.ps1)
|
||
|
|
./scripts/restore.sh backups/<file> # on the new host after `docker compose up`
|
||
|
|
```
|
||
|
|
|
||
|
|
## Tech
|
||
|
|
|
||
|
|
FastAPI + PostgreSQL backend, React + Vite frontend (added in a later milestone), packaged with
|
||
|
|
Docker Compose.
|
||
|
|
|
||
|
|
## Note
|
||
|
|
|
||
|
|
This project is developed with AI assistance.
|