Compare commits
7 Commits
608cc9253d
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 194ed3b87f | |||
| 0cadd5d8d4 | |||
| 32a4d728ef | |||
| 0d9b0302a2 | |||
| d44a8c7276 | |||
| f19577fbcc | |||
| 9f61b06592 |
@@ -27,15 +27,32 @@ jobs:
|
|||||||
STACKS=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '^stacks/' | cut -d'/' -f2 | sort -u || echo "")
|
STACKS=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '^stacks/' | cut -d'/' -f2 | sort -u || echo "")
|
||||||
|
|
||||||
if [ -z "$STACKS" ]; then
|
if [ -z "$STACKS" ]; then
|
||||||
echo "No stacks changed, deploying all..."
|
echo "No stacks changed, checking all stacks..."
|
||||||
STACKS=$(ls stacks/)
|
STACKS=$(ls stacks/)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Deploying: $STACKS"
|
echo "Evaluating stacks: $STACKS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
for stack in $STACKS; do
|
for stack in $STACKS; do
|
||||||
|
COMPOSE_FILE="stacks/$stack/docker-compose.yml"
|
||||||
|
|
||||||
|
# Check stack-type label
|
||||||
|
STACK_TYPE=$(grep -o 'stack-type=[^"]*' "$COMPOSE_FILE" 2>/dev/null | head -1 | cut -d= -f2)
|
||||||
|
|
||||||
|
if [ -z "$STACK_TYPE" ]; then
|
||||||
|
echo "⚠️ SKIP $stack - no stack-type label found"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# On prod, only deploy 'prod' and 'public' stacks
|
||||||
|
if [ "$STACK_TYPE" != "prod" ] && [ "$STACK_TYPE" != "public" ]; then
|
||||||
|
echo "⏭️ SKIP $stack - stack-type=$STACK_TYPE (not for prod)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "Deploying $stack..."
|
echo "Deploying $stack (stack-type=$STACK_TYPE)..."
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
|
|
||||||
STACK_DIR="${{ env.STACKS_DIR }}/$stack"
|
STACK_DIR="${{ env.STACKS_DIR }}/$stack"
|
||||||
@@ -44,9 +61,10 @@ jobs:
|
|||||||
# Copy files
|
# Copy files
|
||||||
sudo cp -r stacks/$stack/* "$STACK_DIR/"
|
sudo cp -r stacks/$stack/* "$STACK_DIR/"
|
||||||
|
|
||||||
# Create .env from template if exists
|
# Create .env from template if .env doesn't exist
|
||||||
if [ -f "$STACK_DIR/.env.template" ]; then
|
if [ -f "$STACK_DIR/.env.template" ] && [ ! -f "$STACK_DIR/.env" ]; then
|
||||||
sudo envsubst < "$STACK_DIR/.env.template" > "$STACK_DIR/.env"
|
echo "Creating .env from template..."
|
||||||
|
sudo sh -c "DOMAIN=$DOMAIN envsubst < '$STACK_DIR/.env.template' > '$STACK_DIR/.env'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Deploy
|
# Deploy
|
||||||
@@ -59,11 +77,11 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: Show running containers
|
- name: Show running containers
|
||||||
run: sudo docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | head -20
|
run: sudo docker ps --format "table {{.Names}}\t{{.Status}}" | head -30
|
||||||
|
|
||||||
deploy-dev:
|
deploy-dev:
|
||||||
if: ${{ github.ref == 'refs/heads/dev' }}
|
if: ${{ github.ref == 'refs/heads/dev' }}
|
||||||
runs-on: ubuntu-dev
|
runs-on: ubuntu-dev:host
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -77,15 +95,32 @@ jobs:
|
|||||||
STACKS=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '^stacks/' | cut -d'/' -f2 | sort -u || echo "")
|
STACKS=$(git diff --name-only HEAD~1 HEAD 2>/dev/null | grep '^stacks/' | cut -d'/' -f2 | sort -u || echo "")
|
||||||
|
|
||||||
if [ -z "$STACKS" ]; then
|
if [ -z "$STACKS" ]; then
|
||||||
echo "No stacks changed, deploying all..."
|
echo "No stacks changed, checking all stacks..."
|
||||||
STACKS=$(ls stacks/)
|
STACKS=$(ls stacks/)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Deploying: $STACKS"
|
echo "Evaluating stacks: $STACKS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
for stack in $STACKS; do
|
for stack in $STACKS; do
|
||||||
|
COMPOSE_FILE="stacks/$stack/docker-compose.yml"
|
||||||
|
|
||||||
|
# Check stack-type label
|
||||||
|
STACK_TYPE=$(grep -o 'stack-type=[^"]*' "$COMPOSE_FILE" 2>/dev/null | head -1 | cut -d= -f2)
|
||||||
|
|
||||||
|
if [ -z "$STACK_TYPE" ]; then
|
||||||
|
echo "⚠️ SKIP $stack - no stack-type label found"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# On dev, only deploy 'dev-only' stacks
|
||||||
|
if [ "$STACK_TYPE" != "dev-only" ]; then
|
||||||
|
echo "⏭️ SKIP $stack - stack-type=$STACK_TYPE (not for dev)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "Deploying $stack..."
|
echo "Deploying $stack (stack-type=$STACK_TYPE)..."
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
|
|
||||||
STACK_DIR="${{ env.STACKS_DIR }}/$stack"
|
STACK_DIR="${{ env.STACKS_DIR }}/$stack"
|
||||||
@@ -94,9 +129,10 @@ jobs:
|
|||||||
# Copy files
|
# Copy files
|
||||||
sudo cp -r stacks/$stack/* "$STACK_DIR/"
|
sudo cp -r stacks/$stack/* "$STACK_DIR/"
|
||||||
|
|
||||||
# Create .env from template if exists
|
# Create .env from template if .env doesn't exist
|
||||||
if [ -f "$STACK_DIR/.env.template" ]; then
|
if [ -f "$STACK_DIR/.env.template" ] && [ ! -f "$STACK_DIR/.env" ]; then
|
||||||
sudo envsubst < "$STACK_DIR/.env.template" > "$STACK_DIR/.env"
|
echo "Creating .env from template..."
|
||||||
|
sudo sh -c "DOMAIN=$DOMAIN envsubst < '$STACK_DIR/.env.template' > '$STACK_DIR/.env'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Deploy
|
# Deploy
|
||||||
@@ -109,4 +145,4 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
- name: Show running containers
|
- name: Show running containers
|
||||||
run: sudo docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | head -20
|
run: sudo docker ps --format "table {{.Names}}\t{{.Status}}" | head -30
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ stacks/
|
|||||||
├── perilous/ # Blog/website
|
├── perilous/ # Blog/website
|
||||||
├── ramz/ # Go web app
|
├── ramz/ # Go web app
|
||||||
├── bookclub/ # Form mailer
|
├── bookclub/ # Form mailer
|
||||||
|
├── invidious/ # YouTube frontend
|
||||||
├── watchtower/ # Auto container updates
|
├── watchtower/ # Auto container updates
|
||||||
├── dockge/ # Container management UI
|
├── dockge/ # Container management UI
|
||||||
└── smokeping/ # Network monitoring
|
└── smokeping/ # Network monitoring
|
||||||
@@ -96,6 +97,13 @@ Set these in Gitea → Repository → Settings → Actions → Secrets:
|
|||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `PERILOUS_CODE_SERVER_PASSWORD` | Code-server password |
|
| `PERILOUS_CODE_SERVER_PASSWORD` | Code-server password |
|
||||||
|
|
||||||
|
### Invidious
|
||||||
|
| Secret | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `INVIDIOUS_DB_PASSWORD` | PostgreSQL password |
|
||||||
|
| `INVIDIOUS_HMAC_KEY` | Generate: `openssl rand -hex 16` |
|
||||||
|
| `INVIDIOUS_COMPANION_KEY` | Generate: `openssl rand -hex 16` (must match companion) |
|
||||||
|
|
||||||
## Runner Setup
|
## Runner Setup
|
||||||
|
|
||||||
The workflow requires a self-hosted runner on the prod server:
|
The workflow requires a self-hosted runner on the prod server:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.form-mailer.rule=Host(`bookclub.${DOMAIN}`)"
|
- "traefik.http.routers.form-mailer.rule=Host(`bookclub.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.form-mailer.entrypoints=https"
|
- "traefik.http.routers.form-mailer.entrypoints=https"
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.dockge.rule=Host(`dockge.${DOMAIN}`)"
|
- "traefik.http.routers.dockge.rule=Host(`dockge.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.dockge.entrypoints=https"
|
- "traefik.http.routers.dockge.entrypoints=https"
|
||||||
@@ -23,3 +24,4 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
web:
|
web:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.filebrowser.entrypoints=https"
|
- "traefik.http.routers.filebrowser.entrypoints=https"
|
||||||
- "traefik.http.routers.filebrowser.rule=Host(`files.${DOMAIN}`)"
|
- "traefik.http.routers.filebrowser.rule=Host(`files.${DOMAIN}`)"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
DOMAIN=${DOMAIN}
|
DOMAIN=${DOMAIN}
|
||||||
INVIDIOUS_DB_PASSWORD=${INVIDIOUS_DB_PASSWORD}
|
INVIDIOUS_DB_PASSWORD=${INVIDIOUS_DB_PASSWORD}
|
||||||
INVIDIOUS_VISITOR_DATA=${INVIDIOUS_VISITOR_DATA}
|
|
||||||
INVIDIOUS_PO_TOKEN=${INVIDIOUS_PO_TOKEN}
|
|
||||||
INVIDIOUS_HMAC_KEY=${INVIDIOUS_HMAC_KEY}
|
INVIDIOUS_HMAC_KEY=${INVIDIOUS_HMAC_KEY}
|
||||||
|
INVIDIOUS_COMPANION_KEY=${INVIDIOUS_COMPANION_KEY}
|
||||||
|
|||||||
12
stacks/invidious/config/sql/annotations.sql
Normal file
12
stacks/invidious/config/sql/annotations.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
-- Table: public.annotations
|
||||||
|
|
||||||
|
-- DROP TABLE public.annotations;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.annotations
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
annotations xml,
|
||||||
|
CONSTRAINT annotations_id_key UNIQUE (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.annotations TO current_user;
|
||||||
30
stacks/invidious/config/sql/channel_videos.sql
Normal file
30
stacks/invidious/config/sql/channel_videos.sql
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
-- Table: public.channel_videos
|
||||||
|
|
||||||
|
-- DROP TABLE public.channel_videos;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.channel_videos
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
title text,
|
||||||
|
published timestamp with time zone,
|
||||||
|
updated timestamp with time zone,
|
||||||
|
ucid text,
|
||||||
|
author text,
|
||||||
|
length_seconds integer,
|
||||||
|
live_now boolean,
|
||||||
|
premiere_timestamp timestamp with time zone,
|
||||||
|
views bigint,
|
||||||
|
CONSTRAINT channel_videos_id_key UNIQUE (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.channel_videos TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.channel_videos_ucid_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.channel_videos_ucid_idx;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS channel_videos_ucid_idx
|
||||||
|
ON public.channel_videos
|
||||||
|
USING btree
|
||||||
|
(ucid COLLATE pg_catalog."default");
|
||||||
|
|
||||||
25
stacks/invidious/config/sql/channels.sql
Normal file
25
stacks/invidious/config/sql/channels.sql
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
-- Table: public.channels
|
||||||
|
|
||||||
|
-- DROP TABLE public.channels;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.channels
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
author text,
|
||||||
|
updated timestamp with time zone,
|
||||||
|
deleted boolean,
|
||||||
|
subscribed timestamp with time zone,
|
||||||
|
CONSTRAINT channels_id_key UNIQUE (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.channels TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.channels_id_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.channels_id_idx;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS channels_id_idx
|
||||||
|
ON public.channels
|
||||||
|
USING btree
|
||||||
|
(id COLLATE pg_catalog."default");
|
||||||
|
|
||||||
22
stacks/invidious/config/sql/nonces.sql
Normal file
22
stacks/invidious/config/sql/nonces.sql
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
-- Table: public.nonces
|
||||||
|
|
||||||
|
-- DROP TABLE public.nonces;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.nonces
|
||||||
|
(
|
||||||
|
nonce text,
|
||||||
|
expire timestamp with time zone,
|
||||||
|
CONSTRAINT nonces_id_key UNIQUE (nonce)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.nonces TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.nonces_nonce_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.nonces_nonce_idx;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS nonces_nonce_idx
|
||||||
|
ON public.nonces
|
||||||
|
USING btree
|
||||||
|
(nonce COLLATE pg_catalog."default");
|
||||||
|
|
||||||
19
stacks/invidious/config/sql/playlist_videos.sql
Normal file
19
stacks/invidious/config/sql/playlist_videos.sql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
-- Table: public.playlist_videos
|
||||||
|
|
||||||
|
-- DROP TABLE public.playlist_videos;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.playlist_videos
|
||||||
|
(
|
||||||
|
title text,
|
||||||
|
id text,
|
||||||
|
author text,
|
||||||
|
ucid text,
|
||||||
|
length_seconds integer,
|
||||||
|
published timestamptz,
|
||||||
|
plid text references playlists(id),
|
||||||
|
index int8,
|
||||||
|
live_now boolean,
|
||||||
|
PRIMARY KEY (index,plid)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.playlist_videos TO current_user;
|
||||||
29
stacks/invidious/config/sql/playlists.sql
Normal file
29
stacks/invidious/config/sql/playlists.sql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
-- Type: public.privacy
|
||||||
|
|
||||||
|
-- DROP TYPE public.privacy;
|
||||||
|
|
||||||
|
CREATE TYPE public.privacy AS ENUM
|
||||||
|
(
|
||||||
|
'Public',
|
||||||
|
'Unlisted',
|
||||||
|
'Private'
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Table: public.playlists
|
||||||
|
|
||||||
|
-- DROP TABLE public.playlists;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.playlists
|
||||||
|
(
|
||||||
|
title text,
|
||||||
|
id text primary key,
|
||||||
|
author text,
|
||||||
|
description text,
|
||||||
|
video_count integer,
|
||||||
|
created timestamptz,
|
||||||
|
updated timestamptz,
|
||||||
|
privacy privacy,
|
||||||
|
index int8[]
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON public.playlists TO current_user;
|
||||||
23
stacks/invidious/config/sql/session_ids.sql
Normal file
23
stacks/invidious/config/sql/session_ids.sql
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
-- Table: public.session_ids
|
||||||
|
|
||||||
|
-- DROP TABLE public.session_ids;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.session_ids
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
email text,
|
||||||
|
issued timestamp with time zone,
|
||||||
|
CONSTRAINT session_ids_pkey PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.session_ids TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.session_ids_id_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.session_ids_id_idx;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS session_ids_id_idx
|
||||||
|
ON public.session_ids
|
||||||
|
USING btree
|
||||||
|
(id COLLATE pg_catalog."default");
|
||||||
|
|
||||||
29
stacks/invidious/config/sql/users.sql
Normal file
29
stacks/invidious/config/sql/users.sql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
-- Table: public.users
|
||||||
|
|
||||||
|
-- DROP TABLE public.users;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS public.users
|
||||||
|
(
|
||||||
|
updated timestamp with time zone,
|
||||||
|
notifications text[],
|
||||||
|
subscriptions text[],
|
||||||
|
email text NOT NULL,
|
||||||
|
preferences text,
|
||||||
|
password text,
|
||||||
|
token text,
|
||||||
|
watched text[],
|
||||||
|
feed_needs_update boolean,
|
||||||
|
CONSTRAINT users_email_key UNIQUE (email)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.users TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.email_unique_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.email_unique_idx;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS email_unique_idx
|
||||||
|
ON public.users
|
||||||
|
USING btree
|
||||||
|
(lower(email) COLLATE pg_catalog."default");
|
||||||
|
|
||||||
23
stacks/invidious/config/sql/videos.sql
Normal file
23
stacks/invidious/config/sql/videos.sql
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
-- Table: public.videos
|
||||||
|
|
||||||
|
-- DROP TABLE public.videos;
|
||||||
|
|
||||||
|
CREATE UNLOGGED TABLE IF NOT EXISTS public.videos
|
||||||
|
(
|
||||||
|
id text NOT NULL,
|
||||||
|
info text,
|
||||||
|
updated timestamp with time zone,
|
||||||
|
CONSTRAINT videos_pkey PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
GRANT ALL ON TABLE public.videos TO current_user;
|
||||||
|
|
||||||
|
-- Index: public.id_idx
|
||||||
|
|
||||||
|
-- DROP INDEX public.id_idx;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS id_idx
|
||||||
|
ON public.videos
|
||||||
|
USING btree
|
||||||
|
(id COLLATE pg_catalog."default");
|
||||||
|
|
||||||
@@ -3,8 +3,6 @@ services:
|
|||||||
image: quay.io/invidious/invidious:latest
|
image: quay.io/invidious/invidious:latest
|
||||||
container_name: invidious
|
container_name: invidious
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
|
||||||
- "3001:3000"
|
|
||||||
environment:
|
environment:
|
||||||
INVIDIOUS_CONFIG: |
|
INVIDIOUS_CONFIG: |
|
||||||
db:
|
db:
|
||||||
@@ -14,45 +12,81 @@ services:
|
|||||||
host: invidious-db
|
host: invidious-db
|
||||||
port: 5432
|
port: 5432
|
||||||
check_tables: true
|
check_tables: true
|
||||||
signature_server: inv_sig_helper:12999
|
invidious_companion:
|
||||||
visitor_data: ${INVIDIOUS_VISITOR_DATA}
|
- private_url: "http://invidious-companion:8282/companion"
|
||||||
po_token: ${INVIDIOUS_PO_TOKEN}
|
public_url: "https://inv.${DOMAIN}"
|
||||||
|
invidious_companion_key: "${INVIDIOUS_COMPANION_KEY}"
|
||||||
|
external_port: 443
|
||||||
|
domain: inv.${DOMAIN}
|
||||||
|
https_only: true
|
||||||
hmac_key: "${INVIDIOUS_HMAC_KEY}"
|
hmac_key: "${INVIDIOUS_HMAC_KEY}"
|
||||||
|
hsts: false
|
||||||
|
log_level: Info
|
||||||
|
healthcheck:
|
||||||
|
test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/trending || exit 1
|
||||||
|
interval: 30s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 2
|
||||||
logging:
|
logging:
|
||||||
options:
|
options:
|
||||||
max-size: "1G"
|
max-size: "1G"
|
||||||
max-file: "4"
|
max-file: "4"
|
||||||
depends_on:
|
depends_on:
|
||||||
- invidious-db
|
- invidious-db
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '1'
|
||||||
|
memory: 2G
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.services.invidious.loadbalancer.server.port=3000"
|
- "traefik.http.services.invidious.loadbalancer.server.port=3000"
|
||||||
- "traefik.http.routers.invidious.entrypoints=https"
|
- "traefik.http.routers.invidious.entrypoints=https"
|
||||||
- "traefik.http.routers.invidious.rule=Host(`invid.${DOMAIN}`, `i.${DOMAIN}`)"
|
- "traefik.http.routers.invidious.rule=Host(`inv.${DOMAIN}`)"
|
||||||
- "traefik.http.routers.invidious.tls.certresolver=http"
|
- "traefik.http.routers.invidious.tls.certresolver=http"
|
||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
- default
|
- default
|
||||||
|
|
||||||
inv_sig_helper:
|
invidious-companion:
|
||||||
image: quay.io/invidious/inv-sig-helper:latest
|
image: quay.io/invidious/invidious-companion:latest
|
||||||
container_name: inv-sig-helper
|
container_name: invidious-companion
|
||||||
command: ["--tcp", "0.0.0.0:12999"]
|
|
||||||
environment:
|
|
||||||
- RUST_LOG=info
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- SERVER_SECRET_KEY=${INVIDIOUS_COMPANION_KEY}
|
||||||
|
- SERVER_BASE_URL=https://inv.${DOMAIN}/companion
|
||||||
|
logging:
|
||||||
|
options:
|
||||||
|
max-size: "1G"
|
||||||
|
max-file: "4"
|
||||||
cap_drop:
|
cap_drop:
|
||||||
- ALL
|
- ALL
|
||||||
read_only: true
|
read_only: true
|
||||||
|
volumes:
|
||||||
|
- companion-cache:/var/tmp/youtubei.js:rw
|
||||||
security_opt:
|
security_opt:
|
||||||
- no-new-privileges:true
|
- no-new-privileges:true
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 1G
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.services.invidious-companion.loadbalancer.server.port=8282"
|
||||||
|
- "traefik.http.routers.invidious-companion.entrypoints=https"
|
||||||
|
- "traefik.http.routers.invidious-companion.rule=Host(`inv.${DOMAIN}`) && PathPrefix(`/companion`)"
|
||||||
|
- "traefik.http.routers.invidious-companion.tls.certresolver=http"
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
- default
|
||||||
|
|
||||||
invidious-db:
|
invidious-db:
|
||||||
image: postgres:14
|
image: postgres:14
|
||||||
container_name: invidious-db
|
container_name: invidious-db
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- ./postgres:/var/lib/postgresql/data
|
- postgres-data:/var/lib/postgresql/data
|
||||||
- ./config/sql:/config/sql
|
- ./config/sql:/config/sql
|
||||||
- ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
|
- ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
|
||||||
environment:
|
environment:
|
||||||
@@ -61,6 +95,15 @@ services:
|
|||||||
POSTGRES_PASSWORD: ${INVIDIOUS_DB_PASSWORD}
|
POSTGRES_PASSWORD: ${INVIDIOUS_DB_PASSWORD}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '0.5'
|
||||||
|
memory: 1G
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
|
companion-cache:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
web:
|
web:
|
||||||
|
|||||||
12
stacks/invidious/docker/init-invidious-db.sh
Executable file
12
stacks/invidious/docker/init-invidious-db.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eou pipefail
|
||||||
|
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/channels.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/videos.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/channel_videos.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/users.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/session_ids.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/nonces.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/annotations.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/playlists.sql
|
||||||
|
psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" < config/sql/playlist_videos.sql
|
||||||
@@ -9,6 +9,8 @@ services:
|
|||||||
- meshmonitor-data:/data
|
- meshmonitor-data:/data
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
volumes:
|
volumes:
|
||||||
meshmonitor-data:
|
meshmonitor-data:
|
||||||
driver: local
|
driver: local
|
||||||
|
|||||||
@@ -5,3 +5,5 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "8585:8080"
|
- "8585:8080"
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
|
|||||||
@@ -12,3 +12,5 @@ services:
|
|||||||
- /etc/ansible/hosts:/etc/ansible/hosts:ro
|
- /etc/ansible/hosts:/etc/ansible/hosts:ro
|
||||||
- ./.ssh:/var/core/mlLogWatcher/.ssh:ro
|
- ./.ssh:/var/core/mlLogWatcher/.ssh:ro
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
environment:
|
environment:
|
||||||
FRONTEND_PORT: "5001"
|
FRONTEND_PORT: "5001"
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -18,3 +18,5 @@ services:
|
|||||||
- /dev/dri:/dev/dri #optional
|
- /dev/dri:/dev/dri #optional
|
||||||
shm_size: "1gb"
|
shm_size: "1gb"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- syncthing
|
- syncthing
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.docker.network=web"
|
- "traefik.docker.network=web"
|
||||||
- "traefik.http.routers.todo-obbytodo.entrypoints=https"
|
- "traefik.http.routers.todo-obbytodo.entrypoints=https"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- web
|
- web
|
||||||
labels:
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.syncthing.entrypoints=https"
|
- "traefik.http.routers.syncthing.entrypoints=https"
|
||||||
- "traefik.http.routers.syncthing.rule=Host(`syncthing.${DOMAIN}`)"
|
- "traefik.http.routers.syncthing.rule=Host(`syncthing.${DOMAIN}`)"
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ services:
|
|||||||
image: szurubooru/server:latest
|
image: szurubooru/server:latest
|
||||||
depends_on:
|
depends_on:
|
||||||
- sql
|
- sql
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
environment:
|
environment:
|
||||||
## These should be the names of the dependent containers listed below,
|
## These should be the names of the dependent containers listed below,
|
||||||
## or FQDNs/IP addresses if these services are running outside of Docker
|
## or FQDNs/IP addresses if these services are running outside of Docker
|
||||||
|
|||||||
12
stacks/tlc/.env.template
Normal file
12
stacks/tlc/.env.template
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Elasticsearch configuration
|
||||||
|
ELASTIC_URL=${ELASTIC_URL}
|
||||||
|
ELASTIC_INDEX=${ELASTIC_INDEX:-tlc-egre}
|
||||||
|
ELASTIC_API_KEY=${ELASTIC_API_KEY}
|
||||||
|
ELASTIC_VERIFY_CERTS=${ELASTIC_VERIFY_CERTS:-0}
|
||||||
|
|
||||||
|
# Qdrant configuration
|
||||||
|
QDRANT_URL=${QDRANT_URL}
|
||||||
|
QDRANT_COLLECTION=${QDRANT_COLLECTION:-tlc-captions-full}
|
||||||
|
QDRANT_VECTOR_NAME=${QDRANT_VECTOR_NAME:-}
|
||||||
|
QDRANT_VECTOR_SIZE=${QDRANT_VECTOR_SIZE:-1024}
|
||||||
|
QDRANT_EMBED_MODEL=${QDRANT_EMBED_MODEL:-BAAI/bge-large-en-v1.5}
|
||||||
74
stacks/tlc/docker-compose.yml
Normal file
74
stacks/tlc/docker-compose.yml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
services:
|
||||||
|
# RSS Bridge - Converts YouTube channels to RSS feeds
|
||||||
|
rss-bridge:
|
||||||
|
image: rssbridge/rss-bridge:latest
|
||||||
|
container_name: tlc-rss-bridge
|
||||||
|
hostname: rss-bridge
|
||||||
|
restart: unless-stopped
|
||||||
|
labels:
|
||||||
|
- "com.ghost.tel/stack-type=dev-only"
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
ports:
|
||||||
|
- "3001:80"
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
# Feed Master - Aggregates multiple RSS feeds into unified feed
|
||||||
|
feed-master:
|
||||||
|
image: umputun/feed-master:latest
|
||||||
|
container_name: tlc-feed-master
|
||||||
|
hostname: feed-master
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- rss-bridge
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
environment:
|
||||||
|
- DEBUG=false
|
||||||
|
- FM_DB=/srv/var/feed-master.bdb
|
||||||
|
- FM_CONF=/srv/etc/fm.yml
|
||||||
|
volumes:
|
||||||
|
- ./feed-master-config:/srv/etc
|
||||||
|
- ./feed-master-data:/srv/var
|
||||||
|
- ./feed-master-images:/srv/images
|
||||||
|
ports:
|
||||||
|
- "8097:8080"
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
# TLC Search - Flask app for searching YouTube transcripts
|
||||||
|
search:
|
||||||
|
image: gitea.ghost.tel/knight/tlc-search:latest
|
||||||
|
container_name: tlc-search
|
||||||
|
hostname: tlc-search
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- feed-master
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "5"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
- RSS_FEED_URL=/rss/youtube-unified
|
||||||
|
- RSS_FEED_UPSTREAM=http://feed-master:8080
|
||||||
|
volumes:
|
||||||
|
- ./channels.yml:/app/python_app/channels.yml:ro
|
||||||
|
- ./data:/app/data:ro
|
||||||
|
ports:
|
||||||
|
- "8088:8080"
|
||||||
|
networks:
|
||||||
|
- web
|
||||||
|
|
||||||
|
networks:
|
||||||
|
web:
|
||||||
|
external: true
|
||||||
168
stacks/tlc/feed-master-config.yml.example
Normal file
168
stacks/tlc/feed-master-config.yml.example
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
# Feed Master Configuration
|
||||||
|
# Auto-generated from channels.yml
|
||||||
|
# Do not edit manually - regenerate using generate_feed_config_simple.py
|
||||||
|
|
||||||
|
feeds:
|
||||||
|
youtube-unified:
|
||||||
|
title: YouTube Unified Feed
|
||||||
|
description: Aggregated feed from all YouTube channels
|
||||||
|
link: https://youtube.com
|
||||||
|
language: "en-us"
|
||||||
|
sources:
|
||||||
|
- name: A Quality Existence
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC6vg0HkKKlgsWk-3HfV-vnw&format=Mrss
|
||||||
|
- name: Adams Fall
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCbD1Pm0TOcRK2zaCrwgcTTg&format=Mrss
|
||||||
|
- name: Andrea with the Bangs
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCeWWxwzgLYUbfjWowXhVdYw&format=Mrss
|
||||||
|
- name: Aphrael Pilotson
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCGHuURJ1XFHzPSeokf6510A&format=Mrss
|
||||||
|
- name: Cassidy van der Kamp
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCM9Z05vuQhMEwsV03u6DrLA&format=Mrss
|
||||||
|
- name: Channel UCCebR16tXbv
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCCebR16tXbv5Ykk9_WtCCug&format=Mrss
|
||||||
|
- name: Channel UCiJmdXTb76i
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCiJmdXTb76i8eIPXdJyf8ZQ&format=Mrss
|
||||||
|
- name: Charlie's Little Corner
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC952hDf_C4nYJdqwK7VzTxA&format=Mrss
|
||||||
|
- name: Chris Howard
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC704NVL2DyzYg3rMU9r1f7A&format=Mrss
|
||||||
|
- name: Christian Baxter
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCU5SNBfTo4umhjYz6M0Jsmg&format=Mrss
|
||||||
|
- name: Climbing Mt Sophia
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCk9O91WwruXmgu1NQrKZZEw&format=Mrss
|
||||||
|
- name: Corner Citizen
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCAXyF_HFeMgwS8nkGVeroAA&format=Mrss
|
||||||
|
- name: Davidbusuttil9086
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCxV18lwwh29DiWuooz7UCvg&format=Mrss
|
||||||
|
- name: Ein Sof - Infinite Reflections
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC4Rmxg7saTfwIpvq3QEzylQ&format=Mrss
|
||||||
|
- name: Emily Rajeh
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCn5mf-fcpBmkepIpZ8eFRng&format=Mrss
|
||||||
|
- name: Eric Seitz
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCTdH4nh6JTcfKUAWvmnPoIQ&format=Mrss
|
||||||
|
- name: Ethan Caughey
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCv2Qft5mZrmA9XAwnl9PU-g&format=Mrss
|
||||||
|
- name: faturechi
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCprytROeCztMOMe8plyJRMg&format=Mrss
|
||||||
|
- name: Finding Ideas
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC6Tvr9mBXNaAxLGRA_sUSRA&format=Mrss
|
||||||
|
- name: Free Rilian
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCT8Lq3ufaGEnCSS8WpFatqw&format=Mrss
|
||||||
|
- name: From Whom All Blessings Flow
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC_-YQbnPfBbIezMr1adZZiQ&format=Mrss
|
||||||
|
- name: Grahampardun
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCB0C8DEIQlQzvSGuGriBxtA&format=Mrss
|
||||||
|
- name: Grail Country
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCsi_x8c12NW9FR7LL01QXKA&format=Mrss
|
||||||
|
- name: Grey Hamilton
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCrZyTWGMdRM9_P26RKPvh3A&format=Mrss
|
||||||
|
- name: Grizwald Grim
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCAqTQ5yLHHH44XWwWXLkvHQ&format=Mrss
|
||||||
|
- name: Jesspurviance
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCQ7rVoApmYIpcmU7fB9RPyw&format=Mrss
|
||||||
|
- name: John Vervaeke
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCpqDUjTsof-kTNpnyWper_Q&format=Mrss
|
||||||
|
- name: Jonathan Dumeer
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC4GiA5Hnwy415uVRymxPK-w&format=Mrss
|
||||||
|
- name: Jonathan Pageau
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCtCTSf3UwRU14nYWr_xm-dQ&format=Mrss
|
||||||
|
- name: Jordan B Peterson
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCL_f53ZEJxp8TtlOkHwMV9Q&format=Mrss
|
||||||
|
- name: Jordan Hall
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCMzT-mdCqoyEv_-YZVtE7MQ&format=Mrss
|
||||||
|
- name: Joseph Lambrecht
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCiOZYvBGHw1Y6wyzffwEp9g&format=Mrss
|
||||||
|
- name: Justinsmorningcoffee
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCPUVeoQYyq8cndWwyczX6RA&format=Mrss
|
||||||
|
- name: Kale Zelden
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCiukuaNd_qzRDTW9qe2OC1w&format=Mrss
|
||||||
|
- name: Lancecleaver227
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCwF5LWNOFou_50bT65bq4Bg&format=Mrss
|
||||||
|
- name: Lucas Vos
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCez1fzMRGctojfis2lfRYug&format=Mrss
|
||||||
|
- name: Luke Thompson
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC_dnk5D4tFCRYCrKIcQlcfw&format=Mrss
|
||||||
|
- name: Marc Jackson
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCMJCtS8jKouJ2d8UIYzW3vg&format=Mrss
|
||||||
|
- name: Mark D Parker
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCVdSgEf9bLXFMBGSMhn7x4Q&format=Mrss
|
||||||
|
- name: Mark S
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC977g6oGYIJDQnsZOGjQBBA&format=Mrss
|
||||||
|
- name: Mary Kochan
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC2leFZRD0ZlQDQxpR2Zd8oA&format=Mrss
|
||||||
|
- name: Matthewparlato5626
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCosBhpwwGh_ueYq4ZSi5dGw&format=Mrss
|
||||||
|
- name: mcmosav
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCnojyPW0IgLWTQ0SaDQ1KBA&format=Mrss
|
||||||
|
- name: Michaelmartin8681
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCpLJJLVB_7v4Igq-9arja1A&format=Mrss
|
||||||
|
- name: More Christ
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCEPOn4cgvrrerg_-q_Ygw1A&format=Mrss
|
||||||
|
- name: Neal Daedalus
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC8mJqpS_EBbMcyuzZDF0TEw&format=Mrss
|
||||||
|
- name: Nechama Gluck
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC5goUoFM4LPim4eY4pwRXYw&format=Mrss
|
||||||
|
- name: OG Rose
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC6zHDj4D323xJkblnPTvY3Q&format=Mrss
|
||||||
|
- name: Paul Anleitner
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC2yCyOMUeem-cYwliC-tLJg&format=Mrss
|
||||||
|
- name: Paul Rene Nichols
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCDCfI162vhPvwdxW6X4nmiw&format=Mrss
|
||||||
|
- name: Paul VanderKlay
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCGsDIP_K6J6VSTqlq-9IPlg&format=Mrss
|
||||||
|
- name: President Foxman
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCMVG5eqpYFVEB-a9IqAOuHA&format=Mrss
|
||||||
|
- name: Rafekelley
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCDIPXp88qjAV3TiaR5Uo3iQ&format=Mrss
|
||||||
|
- name: Randos United
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCEzWTLDYmL8soRdQec9Fsjw&format=Mrss
|
||||||
|
- name: Randos United 2
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC1KgNsMdRoIA_njVmaDdHgA&format=Mrss
|
||||||
|
- name: Rebel Wisdom
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCFQ6Gptuq-sLflbJ4YY3Umw&format=Mrss
|
||||||
|
- name: Restoring Meaning
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCzX6R3ZLQh5Zma_5AsPcqPA&format=Mrss
|
||||||
|
- name: Rigel Windsong Thurston
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCWehDXDEdUpB58P7-Bg1cHg&format=Mrss
|
||||||
|
- name: Rightinchrist
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCZA5mUAyYcCL1kYgxbeMNrA&format=Mrss
|
||||||
|
- name: Ron Copperman
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC5yLuFQCms4nb9K2bGQLqIw&format=Mrss
|
||||||
|
- name: Sartori Studios
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC8SErJkYnDsYGh1HxoZkl-g&format=Mrss
|
||||||
|
- name: Secular Koranism
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCFLovlJ8RFApfjrf2y157xg&format=Mrss
|
||||||
|
- name: Shoulder Serf
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UChptV-kf8lnncGh7DA2m8Pw&format=Mrss
|
||||||
|
- name: Skankenstein
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCUSyTPWW4JaG1YfUPddw47Q&format=Mrss
|
||||||
|
- name: Strange Theology
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCEY1vGNBPsC3dCatZyK3Jkw&format=Mrss
|
||||||
|
- name: The Anadromist
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCIAtCuzdvgNJvSYILnHtdWA&format=Mrss
|
||||||
|
- name: The Chris Show
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UClIDP7_Kzv_7tDQjTv9EhrA&format=Mrss
|
||||||
|
- name: The Meaning Code
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCgp_r6WlBwDSJrP43Mz07GQ&format=Mrss
|
||||||
|
- name: the plebistocrat
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCaJ0CqiiMSTq4X0rycUOIjw&format=Mrss
|
||||||
|
- name: The Young Levite
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC1a4VtU_SMSfdRiwMJR33YQ&format=Mrss
|
||||||
|
- name: TheCommonToad
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC-QiBn6GsM3JZJAeAQpaGAA&format=Mrss
|
||||||
|
- name: TheScrollersPodcast
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UC5uv-BxzCrN93B_5qbOdRWw&format=Mrss
|
||||||
|
- name: Transfigured
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCg7Ed0lecvko58ibuX1XHng&format=Mrss
|
||||||
|
- name: UpCycleClub
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCzw2FNI3IRphcAoVcUENOgQ&format=Mrss
|
||||||
|
- name: Wavesofobsession
|
||||||
|
url: http://rss-bridge/?action=display&bridge=YoutubeBridge&context=By+channel+id&c=UCedgru6YCto3zyXjlbuQuqA&format=Mrss
|
||||||
|
|
||||||
|
system:
|
||||||
|
update: 5m
|
||||||
|
max_per_feed: 5
|
||||||
|
max_total: 200
|
||||||
|
max_keep: 1000
|
||||||
|
base_url: http://localhost:8097
|
||||||
Reference in New Issue
Block a user