# Invidious

**🟢 Active Service**

## 📋 Service Overview

| Property | Value |
|----------|-------|
| **Service Name** | invidious |
| **Host** | concord-nuc (vish-concord-nuc) |
| **Category** | Privacy / Media |
| **Docker Image** | `quay.io/invidious/invidious:latest` |
| **Compose File** | `hosts/physical/concord-nuc/invidious/invidious.yaml` |
| **Portainer Stack** | `invidious-stack` (ID: 584, Endpoint: 443398) |
| **Public URL** | https://in.vish.gg |

## 🎯 Purpose

Invidious is a privacy-respecting alternative YouTube frontend. It strips tracking, allows watching without an account, and supports RSS feeds for subscriptions. Paired with [Materialious](http://concord-nuc:3001) as an alternative Material UI.

## 🐳 Stack Services

The `invidious-stack` compose file defines four services:

| Service | Image | Port | Purpose |
|---------|-------|------|---------|
| `invidious` | `quay.io/invidious/invidious:latest` | 3000 | Main frontend |
| `companion` | `quay.io/invidious/invidious-companion:latest` | 8282 (internal) | YouTube stream handler |
| `invidious-db` | `postgres:14` | 5432 (internal) | PostgreSQL database |
| `materialious` | `wardpearce/materialious:latest` | 3001 | Alternative Material UI |

## 🔧 Configuration

### Invidious Config (`INVIDIOUS_CONFIG`)

```yaml
db:
  dbname: invidious
  user: kemal
  password: "REDACTED_PASSWORD"
  host: invidious-db
  port: 5432
check_tables: true
invidious_companion:
  - private_url: "http://companion:8282/companion"
invidious_companion_key: "pha6nuser7ecei1E"
hmac_key: "Kai5eexiewohchei"
```

### Companion Config

```yaml
SERVER_SECRET_KEY: pha6nuser7ecei1E  # Must match invidious_companion_key; exactly 16 alphanumeric chars
SERVER_BASE_PATH: /companion
HOST: 0.0.0.0
PORT: 8282
```

### Nginx Reverse Proxy

`in.vish.gg` is served by nginx on the NUC (`/etc/nginx/sites-enabled/in.vish.gg.conf`), proxying to `http://127.0.0.1:3000` with TLS via Certbot/Let's Encrypt.

## 🌐 Access

| Interface | URL |
|-----------|-----|
| Public (HTTPS) | https://in.vish.gg |
| Local Invidious | http://192.168.68.100:3000 |
| Local Materialious | http://192.168.68.100:3001 |

## 🔍 Health Monitoring

- **Invidious**: `wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/trending` every 30s
- **invidious-db**: `pg_isready -U kemal -d invidious` every 30s

## 🚨 Troubleshooting

### 502 Bad Gateway on in.vish.gg

Nginx is up but Invidious isn't responding on port 3000. Check container status via Portainer (endpoint `vish-concord-nuc`, stack `invidious-stack`) or:

```bash
# Via Portainer API
curl -s -H "X-API-Key: <key>" \
  "http://vishinator.synology.me:10000/api/endpoints/443398/docker/containers/json?all=true" | \
  jq -r '.[] | select(.Names[0] | test("invidious-stack")) | "\(.Names[0])  \(.State)  \(.Status)"'
```

### Invidious crash-loops: "password authentication failed for user kemal"

**Root cause**: PostgreSQL 14 defaults to `scram-sha-256` auth, which the Crystal DB driver in Invidious does not support.

**Fix**: Change `pg_hba.conf` on the `invidious-db` container to use `trust` for the Docker subnet, then reload:

```bash
# Exec into invidious-db as postgres user (via Portainer API exec or docker exec)
awk '{if(/host all all all scram-sha-256/) print "host all all 172.21.0.0/16 trust"; else print}' \
  /var/lib/postgresql/data/pg_hba.conf > /tmp/hba.tmp && \
  mv /tmp/hba.tmp /var/lib/postgresql/data/pg_hba.conf
psql -U kemal -d invidious -c "SELECT pg_reload_conf();"
```

> **Note**: The `pg_hba.conf` lives inside the `postgresdata` Docker volume, so this change persists across container restarts — but will be lost if the volume is deleted and recreated.

### Companion crash-loops: "SERVER_SECRET_KEY contains invalid characters"

**Root cause**: Portainer's GitOps stack editor can bake the literal string `REDACTED_SECRET_KEY` into the container env when a stack is re-saved via the UI, replacing the real secret with the redaction placeholder.

**Fix**: Update the Portainer stack file via API, replacing `REDACTED_SECRET_KEY` with `pha6nuser7ecei1E`. See `scripts/portainer-emergency-fix.sh` for API key and base URL.

The key must be exactly **16 alphanumeric characters** (a-z, A-Z, 0-9 only — no underscores or special chars).

### Checking logs via Portainer API

```bash
# Get container ID first
ID=$(curl -s -H "X-API-Key: <key>" \
  "http://vishinator.synology.me:10000/api/endpoints/443398/docker/containers/json?all=true" | \
  jq -r '.[] | select(.Names[0] == "/invidious-stack-invidious-1") | .Id')

# Fetch logs (binary Docker stream format — pipe through strings or tr)
curl -s --max-time 10 -H "X-API-Key: <key>" \
  "http://vishinator.synology.me:10000/api/endpoints/443398/docker/containers/${ID}/logs?stdout=1&stderr=1&tail=50" | \
  tr -cd '[:print:]\n'
```

## 📚 Additional Resources

- [Invidious GitHub](https://github.com/iv-org/invidious)
- [Invidious Companion GitHub](https://github.com/iv-org/invidious-companion)
- [Materialious GitHub](https://github.com/WardPearce/Materialious)

---

**Last Updated**: 2026-02-27
**Configuration Source**: `hosts/physical/concord-nuc/invidious/invidious.yaml`
