-
|
Have set up a self hosted instance of TypeType manually and got everything working, but I don't seem to be able to get remote login with Youtube working. Here's my docker compose, it's pretty stock, other than a Traefik reverse proxy and I've moved all the variables into the BTW OIDC I can confirm works fine with PocketID. Don't worry about me exposing any keys, it's not publicly available currently and I'll nuke and pave and generate new values prior to properly deploying. Here's my docker-compose file. networks:
typetype:
external: false
name: typetype
services:
typetype:
image: ghcr.io/priveetee/typetype:latest
container_name: typetype
networks:
traefik:
typetype:
# ports:
# - 8082:80
volumes:
- ${DEPLOY}/typetype/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- typetype-server
restart: unless-stopped
labels:
traefik.enable: "true"
traefik.docker.network: "traefik"
traefik.http.services.typetype.loadbalancer.server.port: "80"
traefik.http.routers.typetype.service: "typetype"
traefik.http.routers.typetype.entrypoints: "websecure"
traefik.http.routers.typetype.rule: "Host(`typetype.${DOMAIN}`)"
# Homepage
homepage.group: "Media"
homepage.name: "typetype"
homepage.icon: "https://icons.${DOMAIN}/typetype"
homepage.href: "https://typetype.${DOMAIN}"
homepage.description: "YouTube Frontend"
typetype-server:
image: ghcr.io/priveetee/typetype-server:latest
container_name: typetype-server
networks:
typetype:
# ports:
# - 8080:8080
env_file: .env
environment:
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS}
DATABASE_URL: ${DATABASE_URL}
DATABASE_USER: ${DATABASE_USER}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
DRAGONFLY_URL: ${DRAGONFLY_URL}
GITHUB_REPO: ${GITHUB_REPO}
GITHUB_ISSUE_TEMPLATE: ${GITHUB_ISSUE_TEMPLATE}
DOWNLOADER_SERVICE_URL: ${DOWNLOADER_SERVICE_URL}
YOUTUBE_REMOTE_LOGIN_SERVICE_URL: ${YOUTUBE_REMOTE_LOGIN_SERVICE_URL}
YOUTUBE_REMOTE_LOGIN_CALLBACK_BASE_URL: ${YOUTUBE_REMOTE_LOGIN_CALLBACK_BASE_URL}
# YOUTUBE_REMOTE_LOGIN_INTERNAL_TOKEN: ${YOUTUBE_REMOTE_LOGIN_INTERNAL_TOKEN}
YOUTUBE_REMOTE_LOGIN_INTERNAL_TOKEN_FILE: ${YOUTUBE_REMOTE_LOGIN_INTERNAL_TOKEN_FILE}
# YOUTUBE_SESSION_ENCRYPTION_KEY: ${YOUTUBE_SESSION_ENCRYPTION_KEY}
YOUTUBE_SESSION_ENCRYPTION_KEY_FILE: ${YOUTUBE_SESSION_ENCRYPTION_KEY_FILE}
YOUTUBE_REMOTE_LOGIN_TTL_MS: ${YOUTUBE_REMOTE_LOGIN_TTL_MS}
YOUTUBE_REMOTE_LOGIN_MAX_SESSIONS: ${YOUTUBE_REMOTE_LOGIN_MAX_SESSIONS}
YOUTUBE_REMOTE_LOGIN_MAX_FRAME_BYTES: ${YOUTUBE_REMOTE_LOGIN_MAX_FRAME_BYTES}
OIDC_ISSUER: ${OIDC_ISSUER}
OIDC_CLIENT_ID: ${OIDC_CLIENT_ID}
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
volumes:
- ${CONFIG}/typetype/typetype-secrets:/run/typetype-secrets:ro
depends_on:
typetype-downloader:
condition: service_started
typetype-dragonfly:
condition: service_started
typetype-postgres-init:
condition: service_completed_successfully
typetype-secrets:
condition: service_completed_successfully
typetype-token:
condition: service_started
restart: unless-stopped
typetype-secrets:
image: busybox:1.37
command:
- /bin/sh
- -ec
- |
generate_secret() {
dd if=/dev/urandom bs=48 count=1 2>/dev/null | base64 | tr '+/' '-_' | tr -d '=\n'
}
ensure_secret() {
file="$$1"
if [ ! -s "$$file" ]; then
generate_secret > "$$file"
fi
chmod 0444 "$$file"
}
mkdir -p /run/typetype-secrets
ensure_secret /run/typetype-secrets/youtube_remote_login_internal_token
ensure_secret /run/typetype-secrets/youtube_session_encryption_key
volumes:
- ${CONFIG}/typetype/typetype-secrets:/run/typetype-secrets
restart: no
typetype-downloader:
image: ghcr.io/priveetee/typetype-downloader:latest
container_name: typetype-downloader
networks:
typetype:
environment:
HTTP_PORT: ${HTTP_PORT}
PUBLIC_BASE_URL: ${PUBLIC_BASE_URL}
TYPETYPE_API_BASE: ${TYPETYPE_API_BASE}
DB_URL: ${DB_URL}
DB_USER: ${DATABASE_USER}
DB_PASSWORD: ${DATABASE_PASSWORD}
REDIS_HOST: ${REDIS_HOST}
REDIS_PORT: ${REDIS_PORT}
REDIS_QUEUE_KEY: ${REDIS_QUEUE_KEY}
MAX_CONCURRENT_WORKERS: ${MAX_CONCURRENT_WORKERS}
MAX_QUEUE_SIZE: ${MAX_QUEUE_SIZE}
JOB_TTL_SECONDS: ${JOB_TTL_SECONDS}
DOWNLOAD_WORKERS: ${DOWNLOAD_WORKERS}
DOWNLOAD_CHUNK_SIZE: ${DOWNLOAD_CHUNK_SIZE}
DOWNLOAD_RANGE_MODE: ${DOWNLOAD_RANGE_MODE}
MUXER: ${MUXER}
STORAGE_BACKEND: ${STORAGE_BACKEND}
S3_ENDPOINT: ${S3_ENDPOINT}
S3_PUBLIC_ENDPOINT: ${S3_PUBLIC_ENDPOINT}
S3_REGION: ${S3_REGION}
S3_BUCKET: ${S3_BUCKET}
S3_ACCESS_KEY: ${S3_ACCESS_KEY}
S3_SECRET_KEY: ${S3_SECRET_KEY}
S3_ARTIFACT_TTL_SECONDS: ${S3_ARTIFACT_TTL_SECONDS}
depends_on:
typetype-postgres-init:
condition: service_completed_successfully
typetype-dragonfly:
condition: service_started
typetype-garage:
condition: service_started
typetype-token:
condition: service_started
restart: unless-stopped
typetype-token:
image: ghcr.io/priveetee/typetype-token:latest
container_name: typetype-token
networks:
typetype:
# ports:
# - 8081:8081
init: true
ipc: host
environment:
NODE_ENV: production
YOUTUBE_REMOTE_LOGIN_ENABLED: ${YOUTUBE_REMOTE_LOGIN_ENABLED}
# YOUTUBE_REMOTE_LOGIN_INTERNAL_TOKEN: ${YOUTUBE_REMOTE_LOGIN_INTERNAL_TOKEN}
YOUTUBE_REMOTE_LOGIN_INTERNAL_TOKEN_FILE: ${YOUTUBE_REMOTE_LOGIN_INTERNAL_TOKEN_FILE}
YOUTUBE_REMOTE_LOGIN_CALLBACK_ORIGIN: ${YOUTUBE_REMOTE_LOGIN_CALLBACK_ORIGIN}
YOUTUBE_REMOTE_LOGIN_MAX_SESSIONS: ${YOUTUBE_REMOTE_LOGIN_MAX_SESSIONS}
YOUTUBE_REMOTE_LOGIN_FRAME_FPS: ${YOUTUBE_REMOTE_LOGIN_FRAME_FPS}
YOUTUBE_REMOTE_LOGIN_MAX_FRAME_BYTES: ${YOUTUBE_REMOTE_LOGIN_MAX_FRAME_BYTES}
volumes:
- ${CONFIG}/typetype/typetype-secrets:/run/typetype-secrets:ro
depends_on:
typetype-secrets:
condition: service_completed_successfully
restart: unless-stopped
typetype-postgres:
image: postgres:17
container_name: typetype-postgres
networks:
typetype:
# ports:
# - 5432:5432
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${DATABASE_USER}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
volumes:
- ${CONFIG}/typetype/typetype-postgres:/var/lib/postgresql/data
restart: unless-stopped
typetype-postgres-init:
image: postgres:17
container_name: typetype-postgres-init
networks:
typetype:
depends_on:
typetype-postgres:
condition: service_started
environment:
PGPASSWORD: ${DATABASE_PASSWORD}
command:
- /bin/sh
- -ec
- |
until pg_isready -h typetype-postgres -U typetype -d typetype; do sleep 1; done
EXISTS=$$(psql -h typetype-postgres -U typetype -d typetype -tAc "SELECT 1 FROM pg_database WHERE datname='typetype_downloader'")
if [ "$$EXISTS" != "1" ]; then
psql -h typetype-postgres -U typetype -d typetype -c "CREATE DATABASE typetype_downloader"
fi
restart: "no"
typetype-dragonfly:
image: docker.dragonflydb.io/dragonflydb/dragonfly:latest
container_name: typetype-dragonfly
networks:
typetype:
ulimits:
memlock: -1
restart: unless-stopped
typetype-garage:
image: dxflrs/garage:v2.2.0
container_name: typetype-garage
networks:
traefik:
typetype:
# ports:
# - 3900:3900
volumes:
- ${DEPLOY}/typetype/garage.toml:/etc/garage.toml:ro
- ${CONFIG}/typetype/typetype-garage/meta:/var/lib/garage/meta
- ${CONFIG}/typetype/typetype-garage/data:/var/lib/garage/data
restart: unless-stopped
labels:
traefik.enable: "true"
traefik.docker.network: "traefik"
traefik.http.services.typetype-garage.loadbalancer.server.port: "3900"
traefik.http.routers.typetype-garage.service: "typetype-garage"
traefik.http.routers.typetype-garage.entrypoints: "websecure"
traefik.http.routers.typetype-garage.rule: "Host(`typetype-garage.${DOMAIN}`)"And here's my I can confirm the secret files have been written correctly (I've changes My metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
db_engine = "sqlite"
replication_factor = 1
rpc_bind_addr = "[::]:3901"
rpc_public_addr = "127.0.0.1:3901"
## Generate with openssl rand -hex 32
rpc_secret = "114aa5d7620efddcf3fcc0f4a882a1e0741bf12314e27a6f2c5a1ca92295be9d"
[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"When I try to login I get this
And the Logs from There are no logs when I check Both the I'm sure I'm missing something, but I can't see the wood for the trees, and would really appreciate some help. |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 2 replies
-
|
Hello! Okay, I’ll look at your problem in more detail a bit later, but yes of course! I can definitely help you. No worries at all 😊 |
Beta Was this translation helpful? Give feedback.
-
|
Hey! I had a look, and from what I can see the first part is actually working: So TypeType-Server is able to start the remote YouTube login session. The problem seems to be here: That route is a WebSocket route, not a normal HTTP GET route. So when it reaches TypeType-Server as a plain GET, Ktor does not match the websocket route and you get a 404. So I think the issue is in the proxy chain, probably the WebSocket upgrade headers are not being forwarded correctly. Can you check the actual nginx file mounted here? ${DEPLOY}/typetype/nginx.conf:/etc/nginx/conf.d/default.conf:roThe proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_buffering off;Also make sure Traefik is not rewriting or stripping the websocket upgrade request before it reaches the Small unrelated thing I noticed too: DATABASE_PASSWORD= ${POSTGRES_PASSWORD}There is a space after DATABASE_PASSWORD=${POSTGRES_PASSWORD}I don’t think that is the websocket issue, but it could create confusing DB auth problems later. If you paste your mounted |
Beta Was this translation helpful? Give feedback.
-
|
I'd tried running without Traefik and had no luck with that. But as always, it was PEBKAC! I was using an old Updated my Here's what I was using: server {
listen 80;
root /usr/share/nginx/html;
index index.html;
client_max_body_size 2g;
gzip on;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
location ^~ /api/ {
client_max_body_size 2g;
proxy_pass http://typetype-server:8080/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
}
location / {
try_files $uri $uri/ /index.html;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}compared to the current version map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
root /usr/share/nginx/html;
index index.html;
client_max_body_size 2g;
gzip on;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
location ^~ /api/ {
client_max_body_size 2g;
proxy_pass http://typetype-server:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 300;
proxy_send_timeout 300;
proxy_buffering off;
}
location / {
try_files $uri $uri/ /index.html;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}I should have checked and looked at your commit history! Just a thought though, is there a reason why |
Beta Was this translation helpful? Give feedback.
-
|
No no, you are not stupid at all :) Honestly this one was easy to miss! The app was starting correctly, the backend route existed, and the failing part only showed up because the request was a websocket upgrade and not a normal HTTP request. So yeah, not obvious at first glance. And your point about The reason it is mounted externally right now is mostly because I wanted self-hosters to be able to tweak it easily if they need a custom setup. But I also don’t have that much experience maintaining self-hosted software for other people yet, so I’m still learning what is annoying in practice. In this case, you are right: having the default Bundling a sane default nginx config inside the I’ll look into this too. Thanks again for testing and reporting it :p |
Beta Was this translation helpful? Give feedback.
-
|
I'm going to own the stupid mistake, I've been doing this long enough to know better! I do agree though, if nginx is bundled then people can stick whatever reverse proxy solution they want in front of it. I absolutely love Typetype and am using it instead of Youtube now. There's still a few things that I come across and hope you don't mind the bug reports, but I definitely think this has loads of potential, if the installation can be streamlined a bit more it would definitely increase the number of people able to host it. |
Beta Was this translation helpful? Give feedback.

I'd tried running without Traefik and had no luck with that. But as always, it was PEBKAC!
I was using an old
nginx.confbefore you updated it, and it was the one thing I hadn't checked, which makes me feel a bit stupid!Updated my
nginx.confand it's working as intended now, sorry for wasting your time!Here's what I was using: