docs: reorganize server documentation (#28)

* docs: reorganize server documentation

* docs: tighten visual design and writing
pull/370/head
zijiren 2 months ago committed by GitHub
parent e9f32205c3
commit 3f1e00b9d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -13,7 +13,7 @@ export default defineConfig({
'zh-CN': 'SyncTV 文档',
en: 'SyncTV Docs',
},
description: 'SyncTV 安装、配置、部署和运维文档',
description: 'SyncTV Server 安装、配置、管理和运维文档',
titleDelimiter: '·',
logo: {
src: './public/logo-notext.svg',
@ -112,389 +112,126 @@ export default defineConfig({
],
sidebar: [
{
label: '总览',
translations: { en: 'Overview' },
items: [
{ label: '项目介绍', translations: { en: 'Overview' }, link: '/' },
{ label: '文档导览', translations: { en: 'Documentation Map' }, slug: 'overview/documentation-map' },
{ label: '讨论与贡献者', translations: { en: 'Discussion and Contributors' }, slug: 'overview/community' },
{ label: '常见任务流程', translations: { en: 'Common Workflows' }, slug: 'overview/common-workflows' },
{ label: '快速开始', translations: { en: 'Quick Start' }, slug: 'install/quick-start' },
{ label: '术语速查', translations: { en: 'Glossary' }, slug: 'reference/glossary' },
],
},
{
label: '概念',
translations: { en: 'Concepts' },
label: '安装与升级',
translations: { en: 'Install and Upgrade' },
items: [
{ label: '概念总览', translations: { en: 'Concepts Overview' }, slug: 'concepts' },
{ label: '房间', translations: { en: 'Rooms' }, slug: 'concepts/rooms' },
{ label: '媒体源', translations: { en: 'Media Sources' }, slug: 'concepts/media-providers' },
{ label: '播放模型', translations: { en: 'Playback Model' }, slug: 'concepts/playback-model' },
{ label: '权限模型', translations: { en: 'Permissions Model' }, slug: 'concepts/permissions' },
{ label: '运行边界', translations: { en: 'Runtime Boundaries' }, slug: 'concepts/runtime-boundaries' },
{ label: '选择部署方式', translations: { en: 'Choose a Deployment' }, slug: 'install/choose-path' },
{ label: 'Docker Compose 快速安装', translations: { en: 'Docker Compose Quick Start' }, slug: 'install/quick-start' },
{ label: 'Docker Compose 参考', translations: { en: 'Docker Compose Reference' }, slug: 'install/docker-compose' },
{ label: 'Helm / Kubernetes', translations: { en: 'Helm / Kubernetes' }, slug: 'install/helm' },
{ label: '生产部署清单', translations: { en: 'Production Checklist' }, slug: 'install/production-checklist' },
{ label: '升级与迁移', translations: { en: 'Upgrades and Migrations' }, slug: 'operations/upgrades' },
{ label: '备份与恢复', translations: { en: 'Backup and Restore' }, slug: 'operations/backup-restore' },
],
collapsed: true,
},
{
label: '使用 SyncTV',
translations: { en: 'Use SyncTV' },
label: '配置',
translations: { en: 'Configuration' },
items: [
{ label: '使用入口', translations: { en: 'Use Overview' }, slug: 'use' },
{ label: '登录与账号安全', translations: { en: 'Sign In and Account Security' }, slug: 'use/accounts-security' },
{ label: '创建和加入房间', translations: { en: 'Create and Join Rooms' }, slug: 'use/rooms' },
{ label: '同步观看', translations: { en: 'Synchronized Playback' }, slug: 'use/synchronized-playback' },
{ label: '聊天', translations: { en: 'Chat' }, slug: 'use/chat' },
{
label: '房间、权限与用户偏好',
translations: { en: 'Rooms, Permissions, and Preferences' },
slug: 'use/rooms-permissions',
},
{
label: '添加媒体',
translations: { en: 'Add Media' },
slug: 'use/media-sources',
{ label: '配置加载与优先级', translations: { en: 'Loading and Precedence' }, slug: 'configuration/how-configuration-works' },
{ label: '配置示例', translations: { en: 'Configuration Examples' }, slug: 'configuration/full-example' },
{ label: '安全与密钥', translations: { en: 'Security and Secrets' }, slug: 'configuration/security' },
{ label: '数据库与 Redis', translations: { en: 'Database and Redis' }, slug: 'configuration/database-and-redis' },
{ label: '服务监听与运行路径', translations: { en: 'Listener and Runtime Paths' }, slug: 'configuration/server-and-runtime' },
{ label: '初始化 root 用户', translations: { en: 'Bootstrap Root User' }, slug: 'configuration/bootstrap' },
{
label: '认证与外部服务',
translations: { en: 'Authentication and External Services' },
items: [
{ label: 'WebAuthn / Passkeys', slug: 'configuration/webauthn' },
{ label: '邮件与 OAuth2', translations: { en: 'Email and OAuth2' }, slug: 'configuration/email-oauth2' },
{ label: '媒体 Provider', translations: { en: 'Media Providers' }, slug: 'configuration/media-providers' },
],
},
{
label: '媒体与实时通信',
translations: { en: 'Media and Realtime' },
items: [
{ label: 'WebRTC', slug: 'configuration/webrtc' },
{ label: '直播', translations: { en: 'Livestreaming' }, slug: 'configuration/livestream' },
{ label: '公开 ID', translations: { en: 'Public IDs' }, slug: 'configuration/public-ids' },
],
},
{
label: '扩展与性能',
translations: { en: 'Scale and Performance' },
items: [
{ label: '集群', translations: { en: 'Cluster' }, slug: 'configuration/cluster' },
{ label: 'Metrics', slug: 'configuration/metrics' },
{ label: '业务缓存', translations: { en: 'Business Cache' }, slug: 'configuration/cache' },
{ label: 'Proxy slice cache', slug: 'configuration/proxy-slice-cache' },
{ label: '限流与连接限制', translations: { en: 'Rate and Connection Limits' }, slug: 'configuration/rate-limits' },
{ label: '内部缓冲区', translations: { en: 'Internal Buffers' }, slug: 'configuration/buffer-sizes' },
],
},
{
label: 'Provider 使用手册',
translations: { en: 'Provider User Guide' },
slug: 'use/provider-guide',
},
{
label: '播放与代理模型',
translations: { en: 'Playback and Proxy Model' },
slug: 'use/playback-and-proxy',
},
{
label: '通知与个人设置',
translations: { en: 'Notifications and Preferences' },
slug: 'use/preferences-notifications',
},
{ label: '用户排障', translations: { en: 'User Troubleshooting' }, slug: 'use/troubleshooting' },
],
collapsed: true,
},
{
label: '管理 SyncTV',
translations: { en: 'Administer SyncTV' },
label: '管理',
translations: { en: 'Administration' },
items: [
{
label: '管理入口',
translations: { en: 'Admin Overview' },
slug: 'admin',
},
{ label: '用户管理', translations: { en: 'User Management' }, slug: 'admin/users' },
{
label: '房间与成员管理',
translations: { en: 'Room and Member Management' },
slug: 'admin/rooms-members',
},
{
label: '审核与治理',
translations: { en: 'Reviews and Moderation' },
slug: 'admin/reviews-moderation',
},
{ label: 'Provider 管理', translations: { en: 'Provider Management' }, slug: 'admin/providers' },
{ label: '管理入口', translations: { en: 'Administration Overview' }, slug: 'admin' },
{ label: '用户', translations: { en: 'Users' }, slug: 'admin/users' },
{ label: '房间与成员', translations: { en: 'Rooms and Members' }, slug: 'admin/rooms-members' },
{ label: '角色、权限与用户偏好', translations: { en: 'Roles, Permissions, and Preferences' }, slug: 'admin/permissions' },
{ label: '审核与治理', translations: { en: 'Reviews and Moderation' }, slug: 'admin/reviews-moderation' },
{ label: 'Provider', slug: 'admin/providers' },
{ label: '运行设置', translations: { en: 'Runtime Settings' }, slug: 'admin/runtime-settings' },
{ label: '认证与安全', translations: { en: 'Authentication and Security' }, slug: 'admin/authentication-security' },
{ label: '数据与保留策略', translations: { en: 'Data and Retention' }, slug: 'operations/data-retention' },
{ label: '维护任务', translations: { en: 'Maintenance Tasks' }, slug: 'admin/maintenance' },
{
label: '认证与安全模型',
translations: { en: 'Authentication and Security Model' },
slug: 'admin/authentication-security',
},
{
label: '数据、隐私与保留策略',
translations: { en: 'Data, Privacy, and Retention' },
slug: 'operations/data-retention',
},
{
label: '安全加固与密钥轮换',
translations: { en: 'Security Hardening and Rotation' },
slug: 'operations/security-hardening-and-rotation',
},
{
label: 'CLI 参考',
translations: { en: 'CLI Reference' },
slug: 'reference/cli',
},
{
label: 'Runtime settings 参考',
translations: { en: 'Runtime Settings Reference' },
slug: 'reference/runtime-settings',
},
],
collapsed: false,
},
{
label: '安装与升级',
translations: { en: 'Install and Upgrade' },
items: [
{
label: '部署路径选择',
translations: { en: 'Choose a Deployment Path' },
slug: 'install/choose-path',
},
{
label: '快速开始',
translations: { en: 'Quick Start' },
slug: 'install/quick-start',
},
{
label: 'Docker Compose 部署',
translations: { en: 'Docker Compose Deployment' },
slug: 'install/docker-compose',
},
{
label: 'Helm 部署',
translations: { en: 'Helm Deployment' },
slug: 'install/helm',
},
{
label: '生产部署清单',
translations: { en: 'Production Checklist' },
slug: 'install/production-checklist',
},
{
label: '备份与恢复',
translations: { en: 'Backup and Restore' },
slug: 'operations/backup-restore',
},
{
label: '升级与迁移',
translations: { en: 'Upgrades and Migrations' },
slug: 'operations/upgrades',
},
{
label: '发布流程',
translations: { en: 'Release Process' },
slug: 'operations/release',
},
],
collapsed: false,
collapsed: true,
},
{
label: '配置 SyncTV',
translations: { en: 'Configure SyncTV' },
label: '运维',
translations: { en: 'Operations' },
items: [
{
label: '配置总索引',
translations: { en: 'Configuration Index' },
slug: 'reference/configuration-index',
},
{
label: '配置文件如何工作',
translations: { en: 'How Configuration Works' },
slug: 'configuration/how-configuration-works',
},
{
label: '完整配置示例',
translations: { en: 'Full Configuration Example' },
slug: 'configuration/full-example',
},
{
label: '服务监听与运行时路径',
translations: { en: 'Server Listener and Runtime Paths' },
slug: 'configuration/server-and-runtime',
},
{
label: '安全与密钥',
translations: { en: 'Security and Secrets' },
slug: 'configuration/security',
},
{
label: '数据库与 Redis',
translations: { en: 'Database and Redis' },
slug: 'configuration/database-and-redis',
},
{
label: '业务缓存',
translations: { en: 'Business Cache' },
slug: 'configuration/cache',
},
{
label: 'Proxy slice cache',
translations: { en: 'Proxy Slice Cache' },
slug: 'configuration/proxy-slice-cache',
},
{
label: 'Metrics 监控',
translations: { en: 'Metrics Monitoring' },
slug: 'configuration/metrics',
},
{
label: '限流与连接限制',
translations: { en: 'Rate Limits and Connection Limits' },
slug: 'configuration/rate-limits',
},
{
label: '媒体 Provider',
translations: { en: 'Media Providers' },
slug: 'configuration/media-providers',
},
{
label: '邮件与 OAuth2',
translations: { en: 'Email and OAuth2' },
slug: 'configuration/email-oauth2',
},
{
label: 'WebAuthn 配置',
translations: { en: 'WebAuthn and Passkeys' },
slug: 'configuration/webauthn',
},
{
label: 'WebRTC 配置',
translations: { en: 'WebRTC Configuration' },
slug: 'configuration/webrtc',
},
{
label: '直播配置',
translations: { en: 'Livestream Configuration' },
slug: 'configuration/livestream',
},
{
label: '集群配置',
translations: { en: 'Cluster Configuration' },
slug: 'configuration/cluster',
},
{
label: '公开 ID',
translations: { en: 'Public IDs' },
slug: 'configuration/public-ids',
},
{
label: '初始化 root 用户',
translations: { en: 'Bootstrap Root User' },
slug: 'configuration/bootstrap',
},
{
label: '内部缓冲区',
translations: { en: 'Internal Buffers' },
slug: 'configuration/buffer-sizes',
},
{ label: '排障', translations: { en: 'Troubleshooting' }, slug: 'operations/troubleshooting' },
{ label: '观测与运行手册', translations: { en: 'Observability Runbook' }, slug: 'operations/observability' },
{ label: '配置校验', translations: { en: 'Configuration Validation' }, slug: 'operations/config-validation' },
{ label: '容量规划', translations: { en: 'Capacity Planning' }, slug: 'operations/capacity-planning' },
{ label: '安全加固与密钥轮换', translations: { en: 'Hardening and Secret Rotation' }, slug: 'operations/security-hardening-and-rotation' },
{ label: '部署与运行边界', translations: { en: 'Deployment and Runtime Boundaries' }, slug: 'operations/deployment-boundaries' },
],
collapsed: false,
collapsed: true,
},
{
label: '开发与集成',
translations: { en: 'Develop with SyncTV' },
translations: { en: 'Development and Integration' },
items: [
{
label: 'Provider 开发指南',
translations: { en: 'Provider Development Guide' },
slug: 'develop/provider-development',
},
{
label: '客户端集成指南',
translations: { en: 'Client Integration Guide' },
slug: 'develop/client-integration',
},
{
label: 'SDK 与 API 示例',
translations: { en: 'SDK and API Examples' },
slug: 'develop/sdk-and-api-examples',
},
{
label: 'Realtime API',
translations: { en: 'Realtime API' },
slug: 'develop/realtime-api',
},
{
label: 'Realtime 资源观察',
translations: { en: 'Realtime Resource Observation' },
slug: 'develop/realtime-resource-observation',
},
{
label: '缓存一致性开发指南',
translations: { en: 'Cache Consistency Development Guide' },
slug: 'develop/cache-consistency',
},
{
label: '实现契约',
translations: { en: 'Implementation Contracts' },
slug: 'develop/implementation-contracts',
},
{
label: 'OpenAPI 文档入口',
translations: { en: 'OpenAPI Access' },
slug: 'reference/openapi',
},
{
label: 'gRPC 调试',
translations: { en: 'gRPC Debugging' },
slug: 'reference/grpc',
},
{
label: '错误参考',
translations: { en: 'Errors' },
slug: 'reference/errors',
},
{
label: 'API 与 protobuf 演进策略',
translations: { en: 'API and Protobuf Evolution' },
slug: 'reference/api-versioning',
},
{
label: '文档写作规范',
translations: { en: 'Documentation Style Guide' },
slug: 'develop/documentation-style-guide',
},
],
collapsed: false,
},
{
label: '运维',
translations: { en: 'Operations' },
items: [
{
label: '排障入口',
translations: { en: 'Troubleshooting' },
slug: 'operations/troubleshooting',
},
{
label: '配置校验',
translations: { en: 'Configuration Validation' },
slug: 'operations/config-validation',
},
{
label: '观测与运行手册',
translations: { en: 'Observability Runbook' },
slug: 'operations/observability',
},
{
label: '容量规划',
translations: { en: 'Capacity Planning' },
slug: 'operations/capacity-planning',
},
{ label: '本地开发', translations: { en: 'Local Development' }, slug: 'develop/local-development' },
{ label: '系统架构', translations: { en: 'Architecture' }, slug: 'overview/architecture' },
{ label: '客户端集成', translations: { en: 'Client Integration' }, slug: 'develop/client-integration' },
{ label: 'SDK 与 API 示例', translations: { en: 'SDK and API Examples' }, slug: 'develop/sdk-and-api-examples' },
{ label: 'Provider 开发', translations: { en: 'Provider Development' }, slug: 'develop/provider-development' },
{ label: '播放与代理协议', translations: { en: 'Playback and Proxy Protocol' }, slug: 'develop/playback-and-proxy' },
{ label: '播放后台任务', translations: { en: 'Playback Background Workers' }, slug: 'develop/playback-background-workers' },
{ label: 'Realtime API', slug: 'develop/realtime-api' },
{ label: 'Realtime 资源观察', translations: { en: 'Realtime Resource Observation' }, slug: 'develop/realtime-resource-observation' },
{ label: '缓存一致性', translations: { en: 'Cache Consistency' }, slug: 'develop/cache-consistency' },
{ label: '实现契约', translations: { en: 'Implementation Contracts' }, slug: 'develop/implementation-contracts' },
{ label: '项目发布流程', translations: { en: 'Project Release Process' }, slug: 'operations/release' },
],
collapsed: false,
collapsed: true,
},
{
label: '参考',
translations: { en: 'Reference' },
items: [
{
label: '配置总索引',
translations: { en: 'Configuration Index' },
slug: 'reference/configuration-index',
},
{
label: '常用环境变量',
translations: { en: 'Environment Variables' },
slug: 'reference/environment-variables',
},
{
label: 'Runtime settings 参考',
translations: { en: 'Runtime Settings Reference' },
slug: 'reference/runtime-settings',
},
{
label: 'Metrics Catalog',
translations: { en: 'Metrics Catalog' },
slug: 'reference/metrics-catalog',
},
{
label: '能力限制与非目标',
translations: { en: 'Limitations and Non-goals' },
slug: 'reference/limitations',
},
{ label: '配置字段', translations: { en: 'Configuration Fields' }, slug: 'reference/configuration-index' },
{ label: '环境变量', translations: { en: 'Environment Variables' }, slug: 'reference/environment-variables' },
{ label: 'Runtime settings', slug: 'reference/runtime-settings' },
{ label: 'CLI', slug: 'reference/cli' },
{ label: 'OpenAPI', slug: 'reference/openapi' },
{ label: 'gRPC', slug: 'reference/grpc' },
{ label: '错误码', translations: { en: 'Errors' }, slug: 'reference/errors' },
{ label: 'API 与 protobuf 演进', translations: { en: 'API and Protobuf Evolution' }, slug: 'reference/api-versioning' },
{ label: 'Metrics Catalog', slug: 'reference/metrics-catalog' },
{ label: '已知限制', translations: { en: 'Known Limitations' }, slug: 'reference/limitations' },
{ label: '术语', translations: { en: 'Glossary' }, slug: 'reference/glossary' },
],
collapsed: true,
},

@ -6,7 +6,7 @@ description: SyncTV 的登录方式、2FA 语义、token 上下文、管理权
import Diagram from '../../../components/Diagram.astro';
import securityAuthBoundaryDiagramDark from '../../../assets/diagrams/security-auth-boundary-zh-dark.svg';
import securityAuthBoundaryDiagramLight from '../../../assets/diagrams/security-auth-boundary-zh-light.svg';
import { Aside, Card, CardGrid, Steps } from '@astrojs/starlight/components';
import { Aside, Steps } from '@astrojs/starlight/components';
## 安全边界
@ -102,32 +102,11 @@ Provider 负责决定上游请求 header。proxy 层只执行 Provider 给出的
- 如果直连 URL 绑定了 `User-Agent`,Provider 返回给客户端的 header 应与服务端代理 header 保持一致。
- 客户端无法设置所需 header 时,应使用代理模式。
Provider 凭据、直连/代理选择和播放信息细节见 [添加媒体](../../use/media-sources/) 和 [播放与代理模型](../../use/playback-and-proxy/)。
Provider 凭据配置见 [媒体 Provider](../../configuration/media-providers/);客户端如何选择直连、代理和播放信息见 [播放与代理协议](../../develop/playback-and-proxy/)。
## 必读配置
<CardGrid>
<Card title="安全与密钥" icon="approve-check-circle">
配置 JWT、OPAQUE、Provider 凭据加密、密码复杂度、CORS 和可信代理。
</Card>
<Card title="邮件与 OAuth2" icon="document">
配置邮箱验证码、SMTP 和运行时 OAuth2 provider 配置。
</Card>
<Card title="WebAuthn" icon="puzzle">
配置 passkey 的 RP ID、origin、允许 origin 和 challenge 超时。
</Card>
<Card title="限流" icon="setting">
配置 HTTP、gRPC、聊天、WebSocket 和认证相关限流。
</Card>
</CardGrid>
## 继续阅读
- [客户端集成指南](../../develop/client-integration/)
- [错误参考](../../reference/errors/)
- [安全加固与密钥轮换](../../operations/security-hardening-and-rotation/)
- [数据、隐私与保留策略](../../operations/data-retention/)
- [安全与密钥](../../configuration/security/)
- [邮件与 OAuth2](../../configuration/email-oauth2/)
- [WebAuthn 配置](../../configuration/webauthn/)
- [限流与连接限制](../../configuration/rate-limits/)
- **安全与密钥**: 配置 JWT、OPAQUE、Provider 凭据加密、密码复杂度、CORS 和可信代理。
- **邮件与 OAuth2**: 配置邮箱验证码、SMTP 和运行时 OAuth2 provider 配置。
- **WebAuthn**: 配置 passkey 的 RP ID、origin、允许 origin 和 challenge 超时。
- **限流**: 配置 HTTP、gRPC、聊天、WebSocket 和认证相关限流。

@ -1,64 +1,31 @@
---
title: 管理 SyncTV
description: 平台管理员管理用户、房间、成员、审核、Provider、直播、运行设置和维护任务。
description: 管理用户、房间、权限、Provider、运行设置和维护任务。
---
import { LinkCard, CardGrid, Aside } from '@astrojs/starlight/components';
import { Aside } from '@astrojs/starlight/components';
管理员文档按管理对象组织。先选择要处理的对象,再进入对应页面查看影响范围、操作顺序和验证方式。
管理命令通过 `synctv admin` 调用 management gRPC。先确认管理入口和认证方式,再执行变更。
<Aside type="caution">
management gRPC、metrics 和内部调试入口不是公网管理面。生产环境优先使用 Unix socket、内网、VPN、堡垒机或 Kubernetes exec;TCP management 必须配置 `management.auth_token`。
management gRPC、metrics 和内部调试入口只应通过 Unix socket、内网、VPN、堡垒机或 Kubernetes exec 访问。TCP management 必须配置 `management.auth_token`。
</Aside>
<CardGrid>
<LinkCard
title="用户管理"
href="./users/"
description="创建用户、封禁和解封、修改全局角色、检查账号安全状态。"
/>
<LinkCard
title="房间与成员管理"
href="./rooms-members/"
description="管理房间生命周期、成员、房间设置、播放控制和直播入口。"
/>
<LinkCard
title="审核与治理"
href="./reviews-moderation/"
description="处理注册、建房、加房审核,以及用户和房间封禁。"
/>
<LinkCard
title="Provider 管理"
href="./providers/"
description="创建、启停、更新、重连、删除 Provider instance,并保护上游凭据。"
/>
<LinkCard
title="运行设置"
href="./runtime-settings/"
description="热更新注册、房间创建、代理策略、CORS、聊天保留等产品策略。"
/>
<LinkCard
title="维护任务"
href="./maintenance/"
description="检查系统状态、清理 stream、驱逐 slice cache、保留操作记录。"
/>
<LinkCard
title="认证与安全模型"
href="./authentication-security/"
description="理解登录方式、2FA、token 上下文、Provider header 和管理面边界。"
/>
</CardGrid>
## 账号与访问
## 管理对象
- [用户](./users/):创建用户、封禁、全局角色和账号安全状态。
- [角色与权限](./permissions/):全局角色、房间角色、权限计算和成员覆盖。
- [认证与安全](./authentication-security/):登录方式、2FA、token 和认证边界。
| 对象 | 常见动作 | 先确认 |
| --- | --- | --- |
| 用户 | 创建、封禁、解封、改角色、查看偏好 | 全局角色、有效状态、2FA 状态 |
| 房间 | 创建、删除、转让、封禁、更新设置 | 创建者、加入规则、成员上限、默认权限 |
| 成员 | 添加、踢出、封禁、改角色、改权限 | 房间角色和成员覆盖是否已经足够 |
| 审核 | 批准或拒绝注册、建房、加房申请 | 申请人、目标房间、拒绝原因 |
| Provider | 创建、启停、更新、重连、删除 | 凭据归属、代理策略、是否仍被引用 |
| 运行设置 | 修改注册、CORS、代理策略等 | 是否属于热更新策略,而不是启动配置 |
| 系统与缓存 | 查看状态、清理 stream、驱逐 slice cache | 是否影响在线播放或缓存命中率 |
## 房间与内容
命令参数见 [CLI 参考](../reference/cli/);完整运行边界见 [运行边界](../concepts/runtime-boundaries/)。
- [房间与成员](./rooms-members/):房间生命周期、成员、播放控制和直播入口。
- [审核与治理](./reviews-moderation/):注册、建房、加房审核和封禁。
- [Provider](./providers/):创建、启停、更新、重连和删除 Provider instance。
## 服务策略与维护
- [运行设置](./runtime-settings/):热更新注册、代理、CORS、聊天和房间策略。
- [维护任务](./maintenance/):检查状态、清理 stream、驱逐缓存并验证结果。
[CLI 参考](../reference/cli/)列出完整参数;[部署与运行边界](../operations/deployment-boundaries/)说明生产依赖和管理面要求。

@ -1,9 +1,8 @@
---
title: 房间、权限与用户偏好
title: 角色、权限与用户偏好
description: SyncTV 的全局用户角色、房间角色、权限名称、房间设置、成员权限覆盖和用户偏好语义。
---
import { Card, CardGrid } from '@astrojs/starlight/components';
import Diagram from '../../../components/Diagram.astro';
import permissionEvaluationDark from '../../../assets/diagrams/permission-evaluation-zh-dark.svg';
import permissionEvaluationLight from '../../../assets/diagrams/permission-evaluation-zh-light.svg';
@ -178,25 +177,7 @@ Provider instance 绑定不是用户偏好;用户通过某个 instance 登录
## 管理策略
<CardGrid>
<Card title="使用权限名称" icon="setting">
权限配置应使用稳定的权限名称集合,便于审查、复制和回滚。
</Card>
<Card title="区分全局和房间" icon="puzzle">
平台 admin 和房间 admin 是两套概念,排查权限问题时先确认操作发生在哪一层。
</Card>
<Card title="偏好不是启动配置" icon="document">
用户偏好可以通过 API/CLI 修改,不应该写进 YAML 或 Helm values。
</Card>
<Card title="变更后验证路径" icon="rocket">
修改加入规则、权限或 2FA 后,用真实登录、加入房间和播放操作验证。
</Card>
</CardGrid>
## 继续阅读
- [管理 SyncTV](../../admin/)
- [认证与安全模型](../../admin/authentication-security/)
- [数据、隐私与保留策略](../../operations/data-retention/)
- [Runtime settings 参考](../../reference/runtime-settings/)
- [CLI 参考](../../reference/cli/)
- **使用权限名称**: 权限配置应使用稳定的权限名称集合,便于审查、复制和回滚。
- **区分全局和房间**: 平台 admin 和房间 admin 是两套概念,排查权限问题时先确认操作发生在哪一层。
- **偏好不是启动配置**: 用户偏好可以通过 API/CLI 修改,不应该写进 YAML 或 Helm values。
- **变更后验证路径**: 修改加入规则、权限或 2FA 后,用真实登录、加入房间和播放操作验证。

@ -40,4 +40,4 @@ synctv provider delete <NAME>
4. 支持 Range 的上游可以 seek。
5. Bilibili、Alist 等对 header 敏感的来源使用了正确的 `User-Agent`、`Referer`、`Range` 和认证 header。
媒体源概念见 [媒体源](../../concepts/media-providers/);用户接入步骤见 [添加媒体](../../use/media-sources/)。
Provider 类型、连接参数和凭据存储见 [媒体 Provider 配置](../../configuration/media-providers/);扩展新 Provider 见 [Provider 开发指南](../../develop/provider-development/)。

@ -33,4 +33,4 @@ description: 管理房间生命周期、成员角色、成员权限、房间设
| 清理扰乱成员 | kick 成员 | 房间封禁不等于平台封禁 |
| 调整长期职责 | 修改房间角色或默认权限 | 不要长期堆叠大量个人覆盖 |
房间对象见 [房间概念](../../concepts/rooms/);权限计算见 [权限模型](../../concepts/permissions/)。
完整的角色、权限计算、房间设置和成员覆盖规则见 [角色、权限与用户偏好](../permissions/)。

@ -42,4 +42,4 @@ synctv user preferences get alice
| 修改 2FA 偏好 | 确认用户至少有两种本地验证方式 |
| 删除账号 | 先评估房间、媒体、审核、通知和审计数据影响 |
账号认证细节见 [认证与安全模型](../authentication-security/);普通用户视角见 [登录与账号安全](../../use/accounts-security/)。
账号认证、2FA、OAuth2、WebAuthn 和 token 边界见 [认证与安全](../authentication-security/)。

@ -1,43 +0,0 @@
---
title: SyncTV 概念
description: 了解房间、媒体源、播放模型、权限和运行边界,再进入具体任务页。
---
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
概念页解释 SyncTV 的产品模型。它们不替代操作指南,也不重复配置字段;当你需要判断一个功能属于哪里、由谁控制、失败时先看哪一层时,从这里开始。
<CardGrid>
<LinkCard
title="房间"
href="./rooms/"
description="房间如何组织成员、播放列表、聊天、直播和设置。"
/>
<LinkCard
title="媒体源"
href="./media-providers/"
description="Provider、直链、远程 Provider、直播入口和播放结果的职责边界。"
/>
<LinkCard
title="播放模型"
href="./playback-model/"
description="当前播放状态、播放信息、Realtime、直连、代理和 Range seek。"
/>
<LinkCard
title="播放后台任务"
href="./playback-background-workers/"
description="时长探测、自动切换和播放资源生命周期任务的本节点 active room 边界。"
/>
<LinkCard
title="权限模型"
href="./permissions/"
description="全局角色、房间角色、成员覆盖、房间设置和用户偏好的关系。"
/>
<LinkCard
title="运行边界"
href="./runtime-boundaries/"
description="PostgreSQL、Redis、secret、管理面、metrics、媒体代理和非目标。"
/>
</CardGrid>
读完概念后,按当前目标进入 [使用 SyncTV](../use/)、[管理 SyncTV](../admin/)、[安装与升级](../install/choose-path/) 或 [开发与集成](../develop/client-integration/)。维护共享行为时同时阅读 [实现契约](../develop/implementation-contracts/)。

@ -1,76 +0,0 @@
---
title: 媒体源
description: Provider、直链、远程 Provider、直播入口和播放结果在 SyncTV 中的职责。
---
SyncTV 不保存媒体文件。它把外部媒体源解析成播放结果,再让客户端直连或通过 SyncTV proxy 播放。这个解析层叫 Provider。
## Provider 做什么
| 能力 | 说明 |
| --- | --- |
| 浏览和搜索 | 从视频网站、直播平台、Alist、Cloudreve、Emby/Jellyfin、NAS 或远程服务列出媒体 |
| 解析播放 | 把选中的媒体转换成播放 URL、代理 URL、header、字幕或变体 |
| 管理凭据 | 保存访问外部服务需要的 token、Cookie、API key 或账号信息 |
| 暴露能力 | 告诉客户端是否支持直连、代理、Range、直播或特定后端能力 |
Provider 返回的是播放决策,不只是一个 URL。客户端应使用 Provider 返回的 header 和代理模式,不要自行猜测 `User-Agent`、`Referer`、Cookie 或 Range 规则。
播放结果可以同时返回原始模式和 proxy 模式,例如 `direct`/`proxy_direct`、`dash`/`proxy_dash`、HLS 清晰度模式及其 proxy sibling。每个 Provider 在 `generate_playback` 阶段完成签名和模式选择,因为 Bilibili DASH、Alist HLS、Emby/Jellyfin 转码、RTMP 和 live proxy 的 URL、header、manifest、字幕和资源生命周期都不同。
`generate_playback` 是 Provider 的播放决策边界。Provider 在这里生成 direct/proxy modes、`default_mode`、headers、signed proxy URLs、manifest/subtitle rewriting、danmaku、thumbnail 和生命周期 metadata。共享 helper 只承担标准 `proxy_*` sibling URL 的机械生成;Provider 自己决定使用时机、默认模式和 header 暴露策略。
Provider cache 的 `VersionedPlayback` 保存原始 `PlaybackResult`、proxy lookup `version` 和 expiry。它服务于缓存命中和 provider-proxy URL 回查;签名后的 response shape 仍由 Provider 的 rewrite callback 生成。缓存命中和新鲜响应必须暴露相同可用的 mode、resolver action、manifest/segment 路由和辅助 URL。
新增或重构 Provider 时,把签名时机、URL 过期、默认 mode、proxy sibling、manifest/segment 重写和直播资源生命周期放在该 Provider 的 `generate_playback` 与 proxy resolver 中一起维护。通用代码只表达跨 Provider 真正一致的机械步骤。
HTTP、gRPC 和管理 API 以 `PlaybackResult` 为事实来源,只做传输参数转换和响应编码。Provider 策略保持在 core provider 层,避免不同传输入口产生不同播放行为。
## Playback 内容契约
| Provider | 必须覆盖的内容 |
| --- | --- |
| Direct URL | upstream mode、`proxy_*` sibling、带 header 源的 proxy default、HLS manifest segment rewriting、Range。 |
| Alist | direct/transcode modes、`proxy_*` siblings、thumbnail、subtitle、HLS segment、stream proxy resolver。 |
| Emby/Jellyfin | upstream/transcode modes、proxy siblings、允许暴露的 upstream token headers、direct stream、HLS/transcode、subtitle proxy。 |
| Bilibili | 匿名播放、DASH/MPD proxy default、proxy manifest segments、字幕、danmaku、thumbnail、缓存 metadata、CDN headers。 |
| RTMP | publish key、stream info、HLS playlist/segment、FLV、provider-proxy URL、idle cleanup。 |
| live proxy | 外部 RTMP/HTTP-FLV 拉流、HLS/FLV provider-proxy URL、publisher 注册、idle cleanup 注销。 |
| 视频平台 | 平台原生清晰度/CDN、字幕、弹幕或聊天、封面、短期 URL 刷新和账号 feed。 |
| NAS/私有云 | 文件/媒体库双路径、Preview/thumbnail、Range、原生转码/remux、播放进度或收藏状态。 |
每个返回给客户端的 URL 都需要真实请求验证。新增 mode 时,同步实现 resolver、缓存命中/失效、URL 过期和手动 E2E 覆盖。
## 常见来源
| 来源 | 适合场景 | 注意点 |
| --- | --- | --- |
| 直链 | URL 已经可被客户端访问 | 特殊 header 可能无法由浏览器设置 |
| Alist | 聚合网盘或文件服务 | 上游认证、目录权限和 Range 支持会影响播放 |
| Emby/Jellyfin | 私有媒体库 | 转码、字幕、码率和用户权限来自上游 |
| Bilibili | 平台视频解析 | Cookie、Referer、UA 和风控变化会影响可用性 |
| Twitch/YouTube/抖音/TikTok | 直播、视频、频道和账号 feed | OAuth scope、Cookie、地区与短期播放 URL |
| 虎牙/斗鱼/AcFun/CCTV | 公开直播与视频解析 | 上游页面和签名协议变化 |
| Cloudreve | 私有云文件与目录 | 服务器可能使用 page 或 cursor 分页 |
| FNOS/QNAP/Synology | NAS 文件与原生媒体库 | 固件版本、媒体服务和转码能力差异 |
| Nextcloud/Seafile/TrueNAS | 私有云文件、收藏与搜索 | 应用密码、资料库解锁和存储路径权限 |
| 远程 Provider | 把媒体解析能力放到独立服务 | 需要稳定的认证、网络和版本约定 |
| RTMP/直播 | 房间内直播和推流 | 多副本时要明确 HLS backend 或 publisher-node proxy |
## 安全边界
Provider 凭据属于敏感信息。生产环境应配置 `security.credential_encryption_key`,并避免把 token、Cookie、API key 写入日志、命令历史或公开配置。删除 Provider instance 前,先确认是否仍被用户默认设置、房间媒体或播放列表引用。
## 端到端验证边界
修改 Provider、proxy、签名、manifest、字幕、RTMP 或 live proxy 行为后,使用构建出的 `synctv` 二进制、`synctv` CLI 和 `curl` 做真实请求验证。覆盖 Direct URL、Alist、Emby、Jellyfin、Bilibili 匿名播放、RTMP、live proxy、HLS、FLV、Range、缓存命中/未命中、URL 过期和资源清理。
验证对象是完整 `PlaybackResult`:每个 mode、每个 URL、每个 manifest、每个 indexed segment、字幕、danmaku、thumbnail 和 proxy sibling 都需要实际请求。CLI 缺少某个工作流时,先补 CLI 入口,再把该工作流纳入手动 E2E。
## 下一步
- 按来源接入媒体:读 [添加媒体](../../use/media-sources/)。
- 理解直连、代理和播放信息:读 [播放模型](../playback-model/)。
- 配置 Provider 行为:读 [媒体 Provider 配置](../../configuration/media-providers/)。
- 逐个 Provider 使用:读 [Provider 使用手册](../../use/provider-guide/)。
- 开发 Provider:读 [Provider 开发指南](../../develop/provider-development/)。

@ -1,34 +0,0 @@
---
title: 权限模型
description: 全局角色、房间角色、成员覆盖、房间设置和用户偏好如何共同决定操作能力。
---
SyncTV 的权限分为平台级和房间级。平台级角色决定能否管理实例;房间级角色和成员覆盖决定用户在某个房间里能做什么。
## 权限来源
| 来源 | 范围 | 示例 |
| --- | --- | --- |
| 全局角色 | 整个实例 | `root`、`admin`、`user` |
| 房间角色 | 单个房间 | `creator`、`admin`、`member`、`guest` |
| 成员覆盖 | 单个用户在单个房间 | 临时允许播放控制、禁言、限制添加媒体 |
| 房间设置 | 单个房间 | 是否允许游客、是否启用聊天、是否需要审核 |
| 用户偏好 | 单个用户 | 2FA、通知偏好、默认 Provider |
## 管理原则
| 场景 | 推荐做法 |
| --- | --- |
| 长期职责变化 | 修改房间角色或角色默认权限 |
| 临时例外 | 使用成员覆盖 |
| 限制所有人发言 | 修改房间聊天设置 |
| 限制单个成员发言 | 移除该成员的 `send_chat_messages` |
| 授权平台管理能力 | 修改全局角色,而不是房间角色 |
平台 `admin` 不自动等于所有房间的房间 `admin`。反过来,房间 `admin` 也不具备平台用户管理、Provider 管理或运行设置修改能力。
## 下一步
- 完整权限名称和计算规则:读 [房间、权限与用户偏好](../../use/rooms-permissions/)。
- 管理房间成员:读 [房间与成员管理](../../admin/rooms-members/)。
- 认证和 2FA:读 [认证与安全模型](../../admin/authentication-security/)。

@ -1,60 +0,0 @@
---
title: 播放模型
description: 当前播放状态、播放信息、Realtime、直连、代理、Range seek 和直播播放的关系。
---
SyncTV 的同步观看由服务端房间状态驱动。客户端不把自己的播放器状态当成事实来源;它接收房间当前播放状态,并在有权限时提交播放控制动作。
## 两类状态
| 状态 | 谁维护 | 用途 |
| --- | --- | --- |
| 当前播放状态 | SyncTV 服务端 | 当前媒体、播放/暂停、进度、速度和版本 |
| 播放信息 | Provider 和 SyncTV 生成 | 播放 URL、代理 URL、header、字幕、变体和过期时间 |
当前播放状态回答“房间正在看什么、看到哪里”。播放信息回答“这个客户端现在应该怎么播放这个媒体”。
## Realtime 如何参与
房间 WebSocket 负责同步播放控制、聊天、WebRTC 信令和资源观察事件。客户端断线重连后,应重新获取关键资源,而不是假设旧订阅仍然存在。
典型顺序:
1. 客户端进入房间。
2. 获取当前播放状态和播放信息。
3. 连接 Realtime。
4. 收到播放、暂停、seek 或切换媒体事件。
5. 如果媒体 URL 过期、Provider 凭据变化或资源版本变化,重新获取播放信息。
## 直连和代理
| 模式 | 适合场景 | 风险 |
| --- | --- | --- |
| 直连 | 客户端能访问上游 URL,并能设置所需 header | 浏览器可能不能设置部分 header |
| SyncTV proxy | 需要隐藏上游凭据、统一 header、处理 Range 或绕过客户端限制 | SyncTV 承担出口带宽和代理延迟 |
Provider 明确返回需要使用的 header。SyncTV proxy 不自动转发客户端原始 header,避免把不该传给上游的信息泄露出去。
同一个播放结果可以同时包含直连模式和 `proxy_*` 模式。Provider 在生成播放信息时决定这些模式、默认模式、header 暴露策略和签名代理 URL。共享 helper 只负责生成标准 proxy sibling URL,不能替代各 Provider 自己的播放决策。
HTTP 和 gRPC 是传输入口。它们解析路径、query、JSON/protobuf、headers 和流式 body,然后调用 `synctv-api/src/impls`。权限、播放状态、Provider 调用、缓存、fanout、时长合并和资源生命周期处理在 `impls` 与 core service 中完成,让两种传输共享同一套行为。
## Range 和缓存
seek 通常依赖 HTTP Range。上游支持 Range 时,SyncTV proxy slice cache 可以缓存固定分片;上游不支持 Range 时,SyncTV 会绕过 slice cache,不把完整大文件写成缓存。
## 后台播放任务
播放时长探测和播放自动切换由本节点 active room 驱动。房间只有在当前进程存在 Realtime 连接时,才会进入该节点的后台播放扫描集合。
这些 worker 在每个节点运行,让后台任务跟随真实连接生命周期。集群中多个节点同时承载同一房间时,数据库负责并发安全:时长探测用任务抢占,自动切换用播放状态事务和乐观版本。
后台任务的输入集合来自 `ConnectionRuntime::active_room_ids()`。Presence hot-room 统计用于房间列表、管理视图和 metrics;播放生命周期 worker 使用本节点实时连接集合,并通过数据库锁、`SKIP LOCKED` 和播放状态版本写入收敛。
动态 playlist 的后台任务还需要绑定当前 target。Repository 查询保留 `room_id = ANY(active_room_ids)` 和当前 `room_playback_progress.target_hash` join,确保探测、缓存和自动切换围绕房间当前播放项进行。
## 下一步
- 普通用户排查播放问题:读 [同步观看](../../use/synchronized-playback/) 和 [用户排障](../../use/troubleshooting/)。
- 客户端实现播放:读 [客户端集成指南](../../develop/client-integration/)。
- 配置代理缓存:读 [Proxy slice cache](../../configuration/proxy-slice-cache/)。

@ -1,37 +0,0 @@
---
title: 房间
description: 房间如何组织成员、播放列表、聊天、直播入口、权限和当前播放状态。
---
房间是 SyncTV 的核心工作空间。一次观影、一组成员、一份播放列表、一套权限和当前播放状态都挂在房间上。用户进入房间后看到的按钮、媒体、聊天和管理入口,取决于房间设置和自己在房间里的角色。
## 房间包含什么
| 内容 | 用途 |
| --- | --- |
| 成员 | 房间创建者、管理员、成员和游客 |
| 播放列表 | 房间内可播放的媒体、子列表和排序 |
| 当前播放 | 当前媒体、播放进度、暂停状态、播放速度和版本 |
| 聊天 | 房间内消息,受发送权限和房间开关控制 |
| 加入规则 | 是否公开、是否需要密码、是否需要审核、成员上限 |
| 权限 | 角色默认权限和成员级覆盖 |
| 直播入口 | RTMP/直播推流和播放会话 |
## 谁能管理房间
全局管理员和房间管理员是两套概念。全局 `root` 或 `admin` 可以通过管理入口维护实例,但不代表普通房间内的所有操作都应该绕过房间权限。房间内的长期职责应优先通过房间角色表达,临时例外再使用成员权限覆盖。
## 常见房间状态
| 状态 | 用户体验 | 管理动作 |
| --- | --- | --- |
| 公开可加入 | 用户打开房间后直接进入 | 控制默认权限和成员上限 |
| 需要密码 | 用户输入房间密码后进入 | 定期更换密码,避免泄露 |
| 需要审核 | 用户提交申请,等待批准 | 处理申请并写清拒绝原因 |
| 暂停使用 | 用户无法继续加入或操作 | 封禁房间或关闭相关入口 |
## 下一步
- 普通用户创建或加入房间:读 [创建和加入房间](../../use/rooms/)。
- 管理成员和房间设置:读 [房间与成员管理](../../admin/rooms-members/)。
- 调整权限:读 [权限模型](../permissions/) 和 [房间、权限与用户偏好](../../use/rooms-permissions/)。

@ -87,11 +87,3 @@ SYNCTV_BOOTSTRAP_ROOT_PASSWORD_FILE=/run/secrets/root_password
| `SYNCTV_BOOTSTRAP_ROOT_USERNAME` | `bootstrap.root_username` |
| `SYNCTV_BOOTSTRAP_ROOT_PASSWORD` | `bootstrap.root_password` |
| `SYNCTV_BOOTSTRAP_ROOT_PASSWORD_FILE` | `bootstrap.root_password` 文件 |
## 继续阅读
- [配置文件如何工作](../how-configuration-works/)
- [安全与密钥](../security/)
- [生产部署清单](../../install/production-checklist/)
- [Docker Compose 部署](../../install/docker-compose/)
- [Helm 部署](../../install/helm/)

@ -61,9 +61,3 @@ buffer_sizes:
- 希望更快暴露审计处理能力不足的问题。
生产环境建议先保持默认,并通过日志或 metrics 观察是否有审计事件丢弃或积压。
## 继续阅读
- [限流与连接限制](../rate-limits/)
- [Metrics 监控](../metrics/)
- [配置总索引](../../reference/configuration-index/)

@ -6,7 +6,7 @@ description: 多副本、Redis 协调、节点发现、leader election、静态
import Diagram from '../../../components/Diagram.astro';
import clusterRuntimeDark from '../../../assets/diagrams/cluster-runtime-zh-dark.svg';
import clusterRuntimeLight from '../../../assets/diagrams/cluster-runtime-zh-light.svg';
import { Aside, Card, CardGrid, Steps } from '@astrojs/starlight/components';
import { Aside, Steps } from '@astrojs/starlight/components';
## 启用条件
@ -44,20 +44,10 @@ openssl rand -hex 32
集群模式解决的是“多个 SyncTV 进程共同服务同一个实例”时的运行时一致性问题。它不是简单的负载均衡开关,也不替代 PostgreSQL、Redis、Ingress 或直播存储/代理策略。
<CardGrid>
<Card title="状态单一来源" icon="seti:db">
PostgreSQL 保存 durable state:用户、房间、权限、Provider、偏好设置和审计数据。所有节点必须连接同一个数据库。
</Card>
<Card title="运行时协调" icon="setting">
Redis 保存 ephemeral/shared state:节点注册、pub/sub、Redis Stream catch-up、leader election、限流和短期认证状态。
</Card>
<Card title="节点间信任" icon="setting">
`cluster.secret` 用于节点间 gRPC 调用认证。所有节点必须一致,且不能暴露给客户端。
</Card>
<Card title="直播可达性" icon="youtube">
RTMP publisher 可能在任意节点上,观众请求也可能落到任意节点;因此直播需要 publisher registry、HLS gRPC proxy 和明确的 HLS 存储边界。
</Card>
</CardGrid>
- **状态单一来源**: PostgreSQL 保存 durable state:用户、房间、权限、Provider、偏好设置和审计数据。所有节点必须连接同一个数据库。
- **运行时协调**: Redis 保存 ephemeral/shared state:节点注册、pub/sub、Redis Stream catch-up、leader election、限流和短期认证状态。
- **节点间信任**: `cluster.secret` 用于节点间 gRPC 调用认证。所有节点必须一致,且不能暴露给客户端。
- **直播可达性**: RTMP publisher 可能在任意节点上,观众请求也可能落到任意节点;因此直播需要 publisher registry、HLS gRPC proxy 和明确的 HLS 存储边界。
<Diagram
light={clusterRuntimeLight}

@ -480,9 +480,3 @@ synctv --config /etc/synctv/synctv.yaml config validate
- TCP management 是否配置了 `management.auth_token`。
- CORS origin、gRPC message size、WebAuthn origin 等字段是否合法。
- 路径类配置能否解析。
## 继续阅读
- [配置总索引](../../reference/configuration-index/):按字段列出类型、默认值和详细说明页面。
- [常用环境变量](../../reference/environment-variables/):列出源码支持的 `SYNCTV_*` 环境变量。
- [配置文件如何工作](../how-configuration-works/):解释优先级、搜索路径、secret 文件和 `data_dir` 路径解析。

@ -6,7 +6,7 @@ description: RTMP、HLS、HTTP-FLV、拉流重试、GOP 缓存和直播存储配
import Diagram from '../../../components/Diagram.astro';
import livestreamPipelineDark from '../../../assets/diagrams/livestream-pipeline-zh-dark.svg';
import livestreamPipelineLight from '../../../assets/diagrams/livestream-pipeline-zh-light.svg';
import { Aside, Card, CardGrid, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
import { Aside, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
## 直播配置控制什么?
@ -25,20 +25,10 @@ import { Aside, Card, CardGrid, Steps, TabItem, Tabs } from '@astrojs/starlight/
caption="直播数据先进入 RTMP/StreamHub,再按播放协议分流:HTTP-FLV 直接面向低延迟播放,HLS remuxer 生成 playlist/segment 并写入选择的 HLS backend。"
/>
<CardGrid>
<Card title="RTMP ingest" icon="youtube">
推流端通过 RTMP 连接进入,认证阶段会把 publisher 注册到本节点或共享 registry。
</Card>
<Card title="StreamHub" icon="cloud-download">
直播包在进程内分发给 FLV session、HLS remuxer 和内部拉流/代理逻辑。
</Card>
<Card title="HTTP-FLV" icon="rocket">
适合低延迟观看。客户端保持长连接,服务端持续写 FLV chunk,并通过写超时保护慢客户端。
</Card>
<Card title="HLS" icon="seti:folder">
适合通用播放器和 CDN/对象存储形态。延迟更高,但对客户端兼容性和多副本扩展更友好。
</Card>
</CardGrid>
- **RTMP ingest**: 推流端通过 RTMP 连接进入,认证阶段会把 publisher 注册到本节点或共享 registry。
- **StreamHub**: 直播包在进程内分发给 FLV session、HLS remuxer 和内部拉流/代理逻辑。
- **HTTP-FLV**: 适合低延迟观看。客户端保持长连接,服务端持续写 FLV chunk,并通过写超时保护慢客户端。
- **HLS**: 适合通用播放器和 CDN/对象存储形态。延迟更高,但对客户端兼容性和多副本扩展更友好。
## 播放协议怎么选?

@ -30,9 +30,7 @@ media_providers:
远程 Provider instance 不是这个 YAML 对象。它通过管理 API/CLI 持久化到数据库,只保存 SyncTV 连接远程 Provider 所需的连接信息,例如 `endpoint`、`tls`、`jwt_secret`、`custom_ca`、`timeout`、`insecure_tls` 和 `providers`。远程 Provider 自己访问 Alist、Emby 或 Bilibili 所需的配置,应放在远程 Provider 服务自己的部署配置中。
按场景接入 Alist、Emby/Jellyfin、Bilibili、直链、RTMP 或远程 Provider 时,先读 [添加媒体](../../use/media-sources/)。
各 Provider 的绑定方式、资源类型和动态播放列表能力见 [Provider 使用手册](../../use/provider-guide/)。实现与扩展流程见 [Provider 开发指南](../../develop/provider-development/)。
通过管理 API 或 CLI 创建远程 Provider instance,并把 Alist、Emby/Jellyfin、Bilibili 等上游配置保留在对应 Provider 服务中。日常启停、重连和凭据维护见 [Provider 管理](../../admin/providers/),实现与扩展流程见 [Provider 开发指南](../../develop/provider-development/)。
## Provider instance
@ -135,11 +133,3 @@ security:
```
否则,创建或更新某些 Provider 凭据可能会被拒绝,或者已有加密凭据无法读取。
## 继续阅读
- [添加媒体](../../use/media-sources/)
- [Provider 使用手册](../../use/provider-guide/)
- [Provider 开发指南](../../develop/provider-development/)
- [播放与代理模型](../../use/playback-and-proxy/)
- [安全加固与密钥轮换](../../operations/security-hardening-and-rotation/)

@ -96,9 +96,3 @@ public_ids:
| --- | --- |
| `SYNCTV_PUBLIC_IDS_SQIDS_ALPHABET` | `public_ids.sqids.alphabet` |
| `SYNCTV_PUBLIC_IDS_SQIDS_MIN_LENGTH` | `public_ids.sqids.min_length` |
## 继续阅读
- [配置文件如何工作](../how-configuration-works/)
- [配置总索引](../../reference/configuration-index/)
- [安全与密钥](../security/)

@ -3,7 +3,7 @@ title: 缓存一致性开发指南
description: 维护 SyncTV 服务端 L1、Redis L2 和 Redis version fence 的强一致性缓存协议。
---
这份文档面向维护服务端缓存代码的开发者。它说明哪些读写路径必须具备强一致性、Redis version fence 如何作为权威新鲜度边界,以及新增缓存时应遵守的实现规则。
服务端缓存由进程内 L1、Redis L2 和 Redis version fence 组成。下面的规则定义强一致读写路径、新鲜度边界和新增缓存的实现要求。
核心原则:**异步失效只负责收敛,不负责正确性**。任何授权、访问控制、房间设置、播放状态、成员身份和资源存在性相关路径,都不能因为某个节点没有收到失效事件而返回旧状态。

@ -17,9 +17,9 @@ OpenAPI 和 protobuf 定义请求、响应和消息结构;客户端还需要
| --- | --- | --- |
| 登录并保持会话 | 登录、处理 MFA、保存 access/refresh token、刷新会话、处理 401 | 本页“Token 使用”和“本地登录和 MFA” |
| 进入房间实时状态 | 获取房间、创建 WebSocket ticket、连接 `/ws/rooms/{roomId}`、解码 protobuf | [Realtime API](../realtime-api/) |
| 展示同步播放 | 读取当前播放状态、获取播放信息、订阅 `playbackState` 和 `playback` | [播放模型](../../concepts/playback-model/) |
| 添加媒体 | 选择 Provider、浏览或搜索媒体、提交播放列表项、处理 Provider 错误 | [媒体源](../../concepts/media-providers/) |
| 处理 URL 过期 | 读取 `expires_at`、到期前刷新播放信息、切换媒体后丢弃旧 URL | [播放与代理模型](../../use/playback-and-proxy/) |
| 展示同步播放 | 读取当前播放状态、获取播放信息、订阅 `playbackState` 和 `playback` | [播放与代理协议](../playback-and-proxy/) |
| 添加媒体 | 选择 Provider、浏览或搜索媒体、提交播放列表项、处理 Provider 错误 | [媒体 Provider 配置](../../configuration/media-providers/) |
| 处理 URL 过期 | 读取 `expires_at`、到期前刷新播放信息、切换媒体后丢弃旧 URL | [播放与代理协议](../playback-and-proxy/) |
| 实现重连 | WebSocket 断开后重新申请 ticket、重连、用本地版本重新观察资源 | [Realtime API](../realtime-api/) |
| 统一错误体验 | 按 HTTP status、业务 code、`requestId`、`Retry-After` 分类处理 | [错误参考](../../reference/errors/) |
@ -424,5 +424,5 @@ HTTP API 的错误体形状:
- [Realtime API](../realtime-api/):WebSocket protobuf、资源观察、版本同步和重连处理。
- [错误参考](../../reference/errors/):HTTP/gRPC/Realtime/Provider 错误结构和错误码。
- [认证与安全模型](../../admin/authentication-security/):2FA、OAuth2、token 上下文和 Provider header 边界。
- [房间、权限与用户偏好](../../use/rooms-permissions/):角色、权限名称、room settings 和用户偏好。
- [角色、权限与用户偏好](../../admin/permissions/):角色、权限名称、room settings 和用户偏好。
- [排障入口](../../operations/troubleshooting/):按现象定位 CORS、WebSocket、登录、Provider 和 Range 问题。

@ -1,93 +0,0 @@
---
title: 文档写作规范
description: SyncTV 文档的信息架构、页面类型、措辞、链接、术语和中英文同步规则。
---
SyncTV 文档按读者任务组织。写文档前先确定读者是谁、读者要完成什么、完成后如何验证。不要把概念解释、操作步骤、字段参考和排障矩阵塞进同一页。
## 页面类型
| 类型 | 用途 | 写法 |
| --- | --- | --- |
| Task | 帮读者完成一个具体动作 | 先给前置条件,再给步骤,最后给验证和失败处理 |
| Concept | 解释产品模型或系统边界 | 说明对象、关系、责任边界和下一步,不放完整字段表 |
| Reference | 查字段、命令、指标、错误码 | 保持结构稳定、可搜索,不承担教学 |
| Troubleshooting | 按现象定位问题 | 用“现象、先检查、交给谁/下一步”组织 |
| Runbook | 管理员或运维执行流程 | 明确影响范围、操作顺序、回滚和验证 |
## 页面开头
首段直接回答“这页帮你做什么”。不要写泛泛的背景介绍。
推荐:
```md
这页说明如何创建房间、设置加入规则,并用普通成员账号验证房间可以正常进入。
```
避免:
```md
本章节将全面介绍 SyncTV 房间相关能力和复杂边界。
```
## 标题
- Task 页标题使用动作:`创建和加入房间`、`添加媒体`。
- Concept 页标题使用名词:`播放模型`、`权限模型`。
- Reference 页标题使用对象:`Runtime settings 参考`、`Metrics Catalog`。
- 标题不写“完整指南”“全面说明”“最佳实践”这类空泛词。
## 措辞
优先使用短句和主动表达。能写具体动作时,不写抽象评价。
| 少用 | 改成 |
| --- | --- |
| 通常应该先确认 | 先检查 |
| 相关页面 | 下一步、参考、继续排查 |
| 语义 | 含义、影响、规则 |
| 边界 | 责任、范围、限制 |
| 生产规则 | 上线前检查、操作规则 |
这些词不是禁用词。配置、安全和架构页可以使用它们,但不能作为固定模板反复出现。
## 链接
- 链接放在读者需要下一步的位置。
- Task 页结尾使用“下一步”,不要机械堆“相关页面”。
- Reference 页可以保留参考链接,但每个链接要有明确用途。
- 不使用旧路径 `deployment/`、`guides/`。
- 不使用脆弱锚点链接指向长页内部标题;优先链接到独立页面。
## 术语
| 术语 | 中文写法 | 英文写法 |
| --- | --- | --- |
| Provider | Provider 或媒体源 Provider | Provider |
| Realtime | Realtime 或实时连接 | Realtime |
| runtime settings | runtime settings 或运行设置 | runtime settings |
| management gRPC | management gRPC 或管理控制面 | management gRPC |
| proxy slice cache | proxy slice cache | proxy slice cache |
首次出现时解释含义,之后保持同一页面内一致。不要把同一概念在同一页里写成多套名字。
## 中英文同步
每个中文页面必须有英文镜像,路径在 `en/` 下保持一致。英文页面按英文产品文档习惯重写,不逐句直译中文:
- 英文用短句。
- 标题用动词或清晰名词。
- 少用 abstract nouns。
- 中文能保留的产品名,英文仍保留产品名。
## 检查
提交文档前运行:
```bash
cd docs
npm run validate
```
校验会检查内部链接、Starlight 图标、旧路径、旧标题、未完成标记和英文镜像。模板化收尾会作为 warning 输出,逐步清理。

@ -3,7 +3,7 @@ title: 实现契约
description: 维护 HTTP/gRPC、Provider 播放、读库、文件存储和播放后台任务时必须遵守的实现规则。
---
这页记录跨模块正确性依赖的实现契约。修改 HTTP/gRPC handler、Provider 播放生成、播放 worker、读库路由、文件存储或 SQLx 查询前,先看这里。
下列契约约束 HTTP/gRPC handler、Provider 播放生成、播放 worker、读库路由、文件存储和 SQLx 查询之间的跨模块行为。
## 传输层和 Impl 层

@ -420,7 +420,7 @@ docker compose config
- 修改运行时入口、依赖关系、Provider/proxy 边界或集群模型时,同步更新 [架构总览](../../overview/architecture/)。
- 修改登录、2FA、OAuth2、token、management 或权限边界时,同步更新 [认证与安全模型](../../admin/authentication-security/)。
- 修改用户、房间、审核、Provider、runtime settings 或管理 CLI 语义时,同步更新 [管理 SyncTV](../../admin/)。
- 修改房间角色、权限名称、room settings、成员覆盖或用户偏好时,同步更新 [房间、权限与用户偏好](../../use/rooms-permissions/)。
- 修改房间角色、权限名称、room settings、成员覆盖或用户偏好时,同步更新 [角色、权限与用户偏好](../../admin/permissions/)。
- 修改 `SettingsRegistry` 注册的热更新字段时,同步更新 [Runtime settings 参考](../../reference/runtime-settings/)。
- 修改 API feature、Swagger UI 路径或 OpenAPI JSON 路径时,同时更新 [OpenAPI 文档入口](../../reference/openapi/)。
- 修改 cluster/admin/service protobuf 时,同时更新 [gRPC 调试](../../reference/grpc/)。

@ -1,5 +1,5 @@
---
title: 播放与代理模型
title: 播放与代理协议
description: SyncTV 播放信息、播放 URL、Provider header、代理模式、Range、slice cache、WebRTC 和直播播放边界。
---
@ -115,10 +115,3 @@ WebRTC 配置见 [WebRTC 配置](../../configuration/webrtc/),直播见 [直
| 只有代理失败 | SyncTV 到上游网络或 header | 服务端网络、DNS、proxy header |
| 多副本直播偶发失败 | HLS 存储模型 | publisher 节点、共享存储、OSS 或 gRPC proxy |
| 播放 URL 一段时间后失效 | `expires_at` | 订阅或重新拉取播放信息 |
## 继续阅读
- [添加媒体](../media-sources/)
- [客户端集成指南](../../develop/client-integration/)
- [Realtime API](../../develop/realtime-api/)
- [容量规划](../../operations/capacity-planning/)

@ -5,7 +5,7 @@ description: 从独立上游客户端到 Core、公开 API、远程传输、CLI
import { Aside, Steps } from '@astrojs/starlight/components';
本指南用于新增 Provider 或扩展现有 Provider。目标是让每个 Provider 保持独立的协议模型、业务能力和产品流程,同时共享稳定的 SyncTV 核心契约。
Provider 实现覆盖上游协议、Core 模型、公开 API、远程传输、CLI、App 和测试。每个 Provider 保留独立的协议模型与能力,并复用稳定的 SyncTV 核心契约。
## 设计原则
@ -281,5 +281,3 @@ flutter test
- [ ] HTTP、gRPC、OpenAPI、management 和 CLI 完成注册。
- [ ] App 完成绑定、能力控制、URL 解析、预览、部分选择和动态播放列表创建。
- [ ] WireMock、Core、API、CLI、Testcontainers 和 Flutter 测试通过。
继续阅读 [实现契约](../implementation-contracts/)、[客户端集成](../client-integration/) 和 [Provider 使用手册](../../use/provider-guide/)。

@ -214,9 +214,3 @@ WebSocket 断开后,观察不会跨连接保留。客户端重连时应该:
| 权限、资源不存在或输入无效 | 重新拉取房间状态,必要时引导用户返回 |
发送失败或连接被服务端断开时,不要假设观察仍然有效。重连后完整重建观察。
## 继续阅读
- 资源字段和订阅示例见 [Realtime 资源观察](../realtime-resource-observation/)。
- 客户端端到端示例见 [SDK 与 API 示例](../sdk-and-api-examples/)。
- 统一错误体验见 [错误参考](../../reference/errors/)。

@ -1,13 +1,13 @@
---
title: SDK 与 API 示例
description: HTTP/OpenAPI、gRPC、WebSocket Realtime 和 Provider API 的最小可运行集成示例。
description: HTTP/OpenAPI、gRPC、WebSocket Realtime 和 Provider API 的可运行示例。
---
import { TabItem, Tabs } from '@astrojs/starlight/components';
## 目标
## 请求顺序
下面是一组可串联执行的 API 示例:登录、刷新 token、创建房间、创建 WebSocket ticket、连接 Realtime、读取播放状态、处理错误和调用 Provider。字段完整定义以 OpenAPI JSON 和 protobuf 为准。
示例依次完成登录、刷新 token、创建房间、创建 WebSocket ticket、连接 Realtime、读取播放状态、处理错误和调用 Provider。字段定义以 OpenAPI JSON 和 protobuf 为准。
先读 [客户端集成指南](../client-integration/) 理解总体约定,再按示例落地代码。
@ -43,7 +43,7 @@ npx openapi-typescript openapi.json -o synctv-api.d.ts
完整入口见 [OpenAPI 文档入口](../../reference/openapi/)。
## HTTP 最小闭环
## HTTP 登录与建房
<Tabs syncKey="http-api-examples">
<TabItem label="OPAQUE 登录" icon="approve-check-circle">
@ -100,7 +100,7 @@ ticket 是短期、一次性、房间绑定凭据。浏览器 WebSocket 使用 t
</TabItem>
</Tabs>
## Realtime 最小闭环
## Realtime 连接与订阅
浏览器示例使用 protobufjs 生成的类型名作为说明,实际导入路径取决于你的构建。
@ -215,10 +215,3 @@ HTTP 错误响应:
| 创建房间、添加媒体、修改设置 | 请求超时后先重新读取资源,避免重复创建 |
| WebSocket 断线 | 重新申请 ticket,重建观察,带上缓存版本 |
| Provider 请求 | 对上游超时做退避,区分凭据失效和上游不可用 |
## 继续阅读
- [客户端集成指南](../client-integration/)
- [Realtime API](../realtime-api/)
- [错误参考](../../reference/errors/)
- [API 与 protobuf 演进策略](../../reference/api-versioning/)

@ -6,7 +6,7 @@ description: SyncTV login methods, 2FA semantics, token context, management perm
import Diagram from '../../../../components/Diagram.astro';
import securityAuthBoundaryDiagramDark from '../../../../assets/diagrams/security-auth-boundary-dark.svg';
import securityAuthBoundaryDiagramLight from '../../../../assets/diagrams/security-auth-boundary-light.svg';
import { Aside, Card, CardGrid, Steps } from '@astrojs/starlight/components';
import { Aside, Steps } from '@astrojs/starlight/components';
## Security Boundaries
@ -102,32 +102,11 @@ Consequences:
- If a direct URL is bound to `User-Agent`, client-facing headers and proxy upstream headers should match.
- If a client cannot set required headers, use proxy mode.
For Provider credentials, direct/proxy selection, and playback info details, see [Add Media](../../use/media-sources/) and [Playback and Proxy Model](../../use/playback-and-proxy/).
See [Media Providers](../../configuration/media-providers/) for credential configuration and [Playback and Proxy Protocol](../../develop/playback-and-proxy/) for direct, proxy, and playback-info selection.
## Required Reading
<CardGrid>
<Card title="Security and Secrets" icon="approve-check-circle">
Configure JWT, OPAQUE, provider credential encryption, password policy, CORS, and trusted proxies.
</Card>
<Card title="Email and OAuth2" icon="document">
Configure email codes, SMTP, and runtime OAuth2 provider settings.
</Card>
<Card title="WebAuthn" icon="puzzle">
Configure passkey RP ID, origins, allowed origins, and challenge timeout.
</Card>
<Card title="Rate Limits" icon="setting">
Configure HTTP, gRPC, chat, WebSocket, and authentication rate limits.
</Card>
</CardGrid>
## Continue Reading
- [Client Integration Guide](../../develop/client-integration/)
- [Errors](../../reference/errors/)
- [Security Hardening and Rotation](../../operations/security-hardening-and-rotation/)
- [Data, Privacy, and Retention](../../operations/data-retention/)
- [Security and Secrets](../../configuration/security/)
- [Email and OAuth2](../../configuration/email-oauth2/)
- [WebAuthn and Passkeys](../../configuration/webauthn/)
- [Rate Limits and Connection Limits](../../configuration/rate-limits/)
- **Security and Secrets**: Configure JWT, OPAQUE, provider credential encryption, password policy, CORS, and trusted proxies.
- **Email and OAuth2**: Configure email codes, SMTP, and runtime OAuth2 provider settings.
- **WebAuthn**: Configure passkey RP ID, origins, allowed origins, and challenge timeout.
- **Rate Limits**: Configure HTTP, gRPC, chat, WebSocket, and authentication rate limits.

@ -1,36 +1,31 @@
---
title: Administer SyncTV
description: Manage users, rooms, members, reviews, Providers, livestreaming, runtime settings, and maintenance tasks.
description: Manage users, rooms, permissions, Providers, runtime settings, and maintenance tasks.
---
import { LinkCard, CardGrid, Aside } from '@astrojs/starlight/components';
import { Aside } from '@astrojs/starlight/components';
Administration docs are organized by managed object. Choose the object first, then read the impact, operation order, and validation steps.
Administration commands call management gRPC through `synctv admin`. Confirm the management endpoint and authentication method before applying changes.
<Aside type="caution">
management gRPC, metrics, and internal debugging endpoints are not public management surfaces. Prefer Unix sockets, private networks, VPNs, bastions, or Kubernetes exec. TCP management must set `management.auth_token`.
Expose management gRPC, metrics, and internal debugging endpoints only through Unix sockets, private networks, VPNs, bastions, or Kubernetes exec. TCP management must set `management.auth_token`.
</Aside>
<CardGrid>
<LinkCard title="User Management" href="./users/" description="Create users, ban and unban, change global roles, and inspect account security state." />
<LinkCard title="Room and Member Management" href="./rooms-members/" description="Manage room lifecycle, members, settings, playback controls, and live entries." />
<LinkCard title="Reviews and Moderation" href="./reviews-moderation/" description="Handle registration, room creation, join reviews, and moderation actions." />
<LinkCard title="Provider Management" href="./providers/" description="Create, enable, disable, update, reconnect, and delete Provider instances." />
<LinkCard title="Runtime Settings" href="./runtime-settings/" description="Hot-update registration, room creation, proxy policy, CORS, and retention policy." />
<LinkCard title="Maintenance Tasks" href="./maintenance/" description="Inspect system state, clear streams, evict slice cache, and validate after maintenance." />
<LinkCard title="Authentication and Security Model" href="./authentication-security/" description="Understand sign-in methods, 2FA, token context, Provider headers, and management boundaries." />
</CardGrid>
## Managed Objects
| Object | Common actions | Check first |
| --- | --- | --- |
| Users | Create, ban, unban, change role, inspect preferences | Global role, effective status, 2FA state |
| Rooms | Create, delete, transfer, ban, update settings | Creator, join rules, member limit, default permissions |
| Members | Add, kick, change role, change permissions | Whether role or member override is the right tool |
| Reviews | Approve or reject registration, room creation, room join | Applicant, target room, rejection reason |
| Providers | Create, enable, disable, update, reconnect, delete | Credential ownership, proxy policy, remaining references |
| Runtime settings | Change registration, CORS, proxy policy, retention | Whether the value is runtime policy, not startup configuration |
| System and cache | Inspect status, clear streams, evict slice cache | Whether the action affects online playback or cache hit rate |
Command flags are in [CLI Reference](../reference/cli/). Runtime boundaries are covered in [Runtime Boundaries](../concepts/runtime-boundaries/).
## Accounts and Access
- [Users](./users/): create users, ban accounts, assign global roles, and inspect account security state.
- [Roles and Permissions](./permissions/): global roles, room roles, permission evaluation, and member overrides.
- [Authentication and Security](./authentication-security/): sign-in methods, 2FA, tokens, and authentication boundaries.
## Rooms and Content
- [Rooms and Members](./rooms-members/): room lifecycle, members, playback controls, and livestream entries.
- [Reviews and Moderation](./reviews-moderation/): registration, room creation, join reviews, and bans.
- [Providers](./providers/): create, enable, disable, update, reconnect, and delete Provider instances.
## Service Policy and Maintenance
- [Runtime Settings](./runtime-settings/): hot-update registration, proxy, CORS, chat, and room policies.
- [Maintenance Tasks](./maintenance/): inspect state, clear streams, evict caches, and verify results.
The [CLI Reference](../reference/cli/) lists every flag. [Deployment and Runtime Boundaries](../operations/deployment-boundaries/) covers production dependencies and management-plane requirements.

@ -1,9 +1,8 @@
---
title: Rooms, Permissions, and Preferences
title: Roles, Permissions, and Preferences
description: SyncTV global user roles, room roles, permission names, room settings, member overrides, and user preferences.
---
import { Card, CardGrid } from '@astrojs/starlight/components';
import Diagram from '../../../../components/Diagram.astro';
import permissionEvaluationDark from '../../../../assets/diagrams/permission-evaluation-dark.svg';
import permissionEvaluationLight from '../../../../assets/diagrams/permission-evaluation-light.svg';
@ -178,25 +177,7 @@ Provider instance bindings are not user preferences. They are stored on provider
## Administration Strategy
<CardGrid>
<Card title="Use Permission Names" icon="setting">
Permission configuration should use stable permission-name sets so changes are readable, reviewable, and easy to roll back.
</Card>
<Card title="Separate Scopes" icon="puzzle">
Platform admin and room admin are separate concepts. Diagnose permission issues by layer first.
</Card>
<Card title="Preferences Are Runtime Data" icon="document">
User preferences are changed through API/CLI and should not live in YAML or Helm values.
</Card>
<Card title="Verify Behavior" icon="rocket">
After changing join rules, permissions, or 2FA, test real login, room join, and playback flows.
</Card>
</CardGrid>
## Continue Reading
- [Administer SyncTV](../../admin/)
- [Authentication and Security Model](../../admin/authentication-security/)
- [Data, Privacy, and Retention](../../operations/data-retention/)
- [Runtime Settings Reference](../../reference/runtime-settings/)
- [CLI Reference](../../reference/cli/)
- **Use Permission Names**: Permission configuration should use stable permission-name sets so changes are readable, reviewable, and easy to roll back.
- **Separate Scopes**: Platform admin and room admin are separate concepts. Diagnose permission issues by layer first.
- **Preferences Are Runtime Data**: User preferences are changed through API/CLI and should not live in YAML or Helm values.
- **Verify Behavior**: After changing join rules, permissions, or 2FA, test real login, room join, and playback flows.

@ -38,4 +38,4 @@ synctv provider delete <NAME>
4. Range seek works for upstreams that support Range.
5. Header-sensitive sources use correct `User-Agent`, `Referer`, `Range`, and authentication headers.
Concepts are in [Media Sources](../../concepts/media-providers/). User-facing setup is in [Add Media](../../use/media-sources/).
See [Media Provider Configuration](../../configuration/media-providers/) for types, connection parameters, and credential storage. See [Provider Development](../../develop/provider-development/) to add a Provider.

@ -33,4 +33,4 @@ Room management affects online users. Query current state first, then validate j
| Remove disruptive member | Kick member | After a kick, the member enters a temporary rejoin cooldown |
| Change long-term responsibility | Change room role or defaults | Avoid long-lived piles of member overrides |
Room concepts are in [Rooms](../../concepts/rooms/). Permission evaluation is in [Permissions Model](../../concepts/permissions/).
See [Roles, Permissions, and Preferences](../permissions/) for role defaults, permission evaluation, room settings, and member overrides.

@ -42,4 +42,4 @@ synctv user preferences get alice
| Change 2FA preference | Confirm at least two local verification methods remain |
| Delete account | Evaluate room, media, review, notification, and audit impact first |
Authentication details are in [Authentication and Security Model](../authentication-security/). User-facing behavior is in [Sign In and Account Security](../../use/accounts-security/).
See [Authentication and Security](../authentication-security/) for 2FA, OAuth2, WebAuthn, and token boundaries.

@ -1,19 +0,0 @@
---
title: SyncTV Concepts
description: Understand rooms, media sources, playback, permissions, and runtime boundaries before using task guides.
---
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
Concept pages explain the product model. Use them when you need to know where a capability belongs, who controls it, and which layer to inspect when it fails.
<CardGrid>
<LinkCard title="Rooms" href="./rooms/" description="How rooms organize members, playlists, chat, livestreaming, and settings." />
<LinkCard title="Media Sources" href="./media-providers/" description="Provider, direct URL, remote Provider, livestream, and playback result boundaries." />
<LinkCard title="Playback Model" href="./playback-model/" description="Playback state, playback info, Realtime, direct URLs, proxying, and Range seek." />
<LinkCard title="Playback Background Workers" href="./playback-background-workers/" description="Node-local active room boundaries for duration probing, auto-advance, and playback resource lifecycle work." />
<LinkCard title="Permissions Model" href="./permissions/" description="Global roles, room roles, member overrides, room settings, and preferences." />
<LinkCard title="Runtime Boundaries" href="./runtime-boundaries/" description="PostgreSQL, Redis, secrets, management endpoints, metrics, proxying, and non-goals." />
</CardGrid>
After the concepts, continue with [Use SyncTV](../use/), [Administer SyncTV](../admin/), [Install and Upgrade](../install/choose-path/), or [Develop with SyncTV](../develop/client-integration/). Maintainers changing shared behavior should also read [Implementation Contracts](../develop/implementation-contracts/).

@ -1,80 +0,0 @@
---
title: Media Sources
description: Provider, direct URL, remote Provider, livestream, and playback result responsibilities in SyncTV.
---
SyncTV does not store media files. It resolves external media into playback results, then lets clients play directly or through the SyncTV proxy. The resolving layer is called a Provider.
## What Providers Do
| Capability | Meaning |
| --- | --- |
| Browse and search | List media from video platforms, live platforms, Alist, Cloudreve, Emby/Jellyfin, NAS systems, or remote services |
| Resolve playback | Return playback URLs, proxy URLs, headers, subtitles, variants, or metadata |
| Manage credentials | Store tokens, cookies, API keys, or account credentials for upstream services |
| Expose behavior | Tell clients whether direct play, proxying, Range, livestreaming, or backend features are available |
A Provider returns a playback decision, not only a URL. Clients should use the headers and proxy mode returned by the Provider instead of inventing `User-Agent`, `Referer`, Cookie, or Range rules.
A playback result can return upstream and proxy modes together, such as `direct`/`proxy_direct`, `dash`/`proxy_dash`, HLS quality modes, and their proxy siblings. Each Provider performs signing and mode selection during `generate_playback` because Bilibili DASH, Alist HLS, Emby/Jellyfin transcoding, RTMP, and live proxy all have different URLs, headers, manifests, subtitles, and resource lifecycles.
`generate_playback` is the Provider playback decision boundary. Providers create direct/proxy modes, `default_mode`, headers, signed proxy URLs, manifest/subtitle rewriting, danmaku, thumbnails, and lifecycle metadata there. Shared helpers only perform mechanical `proxy_*` sibling URL generation; each Provider chooses when to use them, which mode is default, and which headers are exposed.
Provider cache stores `VersionedPlayback`: the raw `PlaybackResult`, proxy
lookup `version`, and expiry. It supports cache hits and provider-proxy URL
lookup; the signed response shape still comes from the Provider rewrite
callback. Cache hits and fresh responses must expose the same usable modes,
resolver actions, manifest/segment routes, and auxiliary URLs.
When adding or refactoring a Provider, keep signing timing, URL expiry, default mode, proxy siblings, manifest/segment rewriting, and live resource lifecycle inside that Provider's `generate_playback` and proxy resolver. Shared code should express mechanical steps that are genuinely common across Providers.
HTTP, gRPC, and management APIs treat `PlaybackResult` as the source of truth. They translate transport parameters and encode responses while Provider policy stays in the core provider layer.
## Playback Content Contract
| Provider | Required coverage |
| --- | --- |
| Direct URL | upstream mode, `proxy_*` sibling, proxy default for sources with headers, HLS manifest segment rewriting, Range. |
| Alist | direct/transcode modes, `proxy_*` siblings, thumbnail, subtitle, HLS segment, stream proxy resolver. |
| Emby/Jellyfin | upstream/transcode modes, proxy siblings, allowed upstream token headers, direct stream, HLS/transcode, subtitle proxy. |
| Bilibili | anonymous playback, DASH/MPD proxy default, proxy manifest segments, subtitles, danmaku, thumbnails, cache metadata, CDN headers. |
| RTMP | publish key, stream info, HLS playlist/segment, FLV, provider-proxy URL, idle cleanup. |
| live proxy | external RTMP/HTTP-FLV pull, HLS/FLV provider-proxy URL, publisher registration, idle cleanup unregister. |
| Video platforms | Native quality/CDN choices, subtitles, danmaku or chat, covers, short-lived URL refresh, and account feeds. |
| NAS/private cloud | File/media-library paths, previews, Range, native transcode/remux, playback progress, and favorite state. |
Every URL returned to clients needs a real request test. When adding a mode, add the resolver, cache hit/expiry handling, URL expiry handling, and manual E2E coverage at the same time.
## Common Sources
| Source | Good for | Watch out for |
| --- | --- | --- |
| Direct URL | A stable URL already reachable by clients | Browser header restrictions |
| Alist | Cloud drive and file browsing | Upstream auth, directory permissions, Range support |
| Emby/Jellyfin | Existing media libraries | Transcoding, subtitles, bitrate, upstream user permissions |
| Bilibili | Platform video resolving | Cookie, Referer, UA, and upstream policy changes |
| Twitch/YouTube/Douyin/TikTok | Live, video, channel, and account feeds | OAuth scopes, Cookies, region, and short-lived playback URLs |
| Huya/Douyu/AcFun/CCTV | Public live and video resolution | Upstream page and signing protocol changes |
| Cloudreve | Private-cloud files and folders | Servers can use page or cursor pagination |
| FNOS/QNAP/Synology | NAS files and native media libraries | Firmware, media-service, and transcoding capability differences |
| Nextcloud/Seafile/TrueNAS | Private-cloud files, favorites, and search | App passwords, library unlock, and storage-path permissions |
| Remote Provider | Isolating media resolving into another service | Auth, network, and version compatibility |
| RTMP/live | Room livestreaming | Multi-replica HLS backend or publisher-node proxy |
## Security Boundary
Provider credentials are sensitive. Configure `security.credential_encryption_key` in production, and keep tokens, cookies, and API keys out of logs, shell history, and public configuration.
## End-to-End Verification Boundary
After changing Provider, proxy, signing, manifest, subtitle, RTMP, or live proxy behavior, verify with a built `synctv` binary, the `synctv` CLI, and `curl`. Cover Direct URL, Alist, Emby, Jellyfin, Bilibili anonymous playback, RTMP, live proxy, HLS, FLV, Range, cache miss/hit paths, URL expiry, and cleanup.
The verification target is the full `PlaybackResult`: every mode, URL, manifest, indexed segment, subtitle, danmaku, thumbnail, and proxy sibling should be requested. Add CLI coverage before accepting a provider workflow that can only be exercised through direct database writes or ad hoc internal calls.
## Next Steps
- Add media by source: [Add Media](../../use/media-sources/).
- Understand direct/proxy playback: [Playback Model](../playback-model/).
- Configure Provider behavior: [Media Providers](../../configuration/media-providers/).
- Use each Provider: [Provider User Guide](../../use/provider-guide/).
- Develop Providers: [Provider Development Guide](../../develop/provider-development/).

@ -1,34 +0,0 @@
---
title: Permissions Model
description: How global roles, room roles, member overrides, room settings, and user preferences determine allowed actions.
---
SyncTV permissions have platform scope and room scope. Platform roles decide who can administer the instance. Room roles and member overrides decide what a user can do in one room.
## Permission Sources
| Source | Scope | Examples |
| --- | --- | --- |
| Global role | Whole instance | `root`, `admin`, `user` |
| Room role | One room | `creator`, `admin`, `member`, `guest` |
| Member override | One user in one room | Temporary playback control, mute, media restriction |
| Room setting | One room | Guest access, chat enabled, review required |
| User preference | One user | 2FA, notification preference, default Provider |
## Management Principles
| Situation | Prefer |
| --- | --- |
| Long-term responsibility change | Change room role or role defaults |
| Temporary exception | Use a member override |
| Restrict everyone from chatting | Change the room chat setting |
| Restrict one member from chatting | Remove that member's `send_chat_messages` |
| Grant platform administration | Change the global role |
A platform `admin` is not automatically a room `admin` in every room. A room `admin` cannot manage platform users, Providers, or runtime settings.
## Next Steps
- Full permission names and evaluation rules: [Rooms, Permissions, and Preferences](../../use/rooms-permissions/).
- Member management: [Room and Member Management](../../admin/rooms-members/).
- Authentication and 2FA: [Authentication and Security Model](../../admin/authentication-security/).

@ -1,58 +0,0 @@
---
title: Playback Model
description: How playback state, playback info, Realtime, direct URLs, proxying, Range seek, and livestreaming fit together.
---
Synchronized watching is driven by server-side room state. A client should not treat its local player state as the source of truth. It follows room playback state and submits control actions only when the user has permission.
## Two Kinds of State
| State | Owner | Used for |
| --- | --- | --- |
| Current playback state | SyncTV server | Current media, play/pause, position, speed, and version |
| Playback info | Provider and SyncTV | Playback URL, proxy URL, headers, subtitles, variants, and expiry |
Current playback state answers “what is the room watching and where is it?”. A playback info answers “how should this client play that media now?”.
## Realtime Flow
Room WebSocket connections carry playback controls, chat, WebRTC signaling, and resource observation events. After reconnecting, clients should fetch key resources again instead of assuming old subscriptions are still active.
1. Enter a room.
2. Fetch current playback state and a playback info.
3. Connect Realtime.
4. Receive play, pause, seek, or media-change events.
5. Refresh the playback info when the media URL expires, Provider credentials change, or room resources change.
## Direct and Proxy Playback
| Mode | Good for | Risk |
| --- | --- | --- |
| Direct | Clients can reach the upstream URL and set required headers | Browsers may block required headers |
| SyncTV proxy | Hide upstream credentials, normalize headers, handle Range, or cross client limits | SyncTV carries egress bandwidth and proxy latency |
Providers explicitly return the headers to use. The proxy does not forward arbitrary client headers to upstream services.
One playback result can contain direct modes and `proxy_*` modes at the same time. Each Provider decides these modes, the default mode, header exposure, and signed proxy URLs while generating playback info. Shared helpers only generate standard proxy sibling URLs; they do not replace provider-owned playback decisions.
HTTP and gRPC are transport entry points. They parse paths, query parameters, JSON/protobuf, headers, and streaming bodies, then call `synctv-api/src/impls`. Permissions, playback state, Provider calls, caching, fanout, duration merging, and resource lifecycle handling live in `impls` and core services so both transports share one behavior path.
## Range and Cache
Seeking usually depends on HTTP Range. When upstream supports Range, proxy slice cache can cache fixed byte slices. If upstream does not support Range, SyncTV bypasses slice cache and does not write full-file cache entries.
## Playback Background Workers
Duration probing and playback auto-advance are driven by local active rooms. A room enters a node's playback background scan set only while the current process has a Realtime connection for that room.
These workers run on every node so background work follows the real connection lifecycle. When several cluster nodes host the same room, the database provides concurrency safety: duration probes claim work, and auto-advance uses playback state transactions with optimistic versions.
The worker input set comes from `ConnectionRuntime::active_room_ids()`. Presence hot-room statistics serve room lists, admin views, and metrics. Playback lifecycle workers use the node-local realtime connection set, while database locks, `SKIP LOCKED`, and playback-state version writes converge duplicate cross-node attempts.
Dynamic playlist background work also stays bound to the current target. Repository queries keep both `room_id = ANY(active_room_ids)` and the current `room_playback_progress.target_hash` join so probing, caching, and auto-advance operate on the item the room is currently playing.
## Next Steps
- User playback issues: [Synchronized Playback](../../use/synchronized-playback/) and [User Troubleshooting](../../use/troubleshooting/).
- Client implementation: [Client Integration Guide](../../develop/client-integration/).
- Proxy cache configuration: [Proxy Slice Cache](../../configuration/proxy-slice-cache/).

@ -1,37 +0,0 @@
---
title: Rooms
description: How rooms organize members, playlists, chat, livestreaming, permissions, and current playback.
---
A room is the main workspace in SyncTV. One watching session, a set of members, a playlist, permissions, and current playback state all belong to a room. The controls a user sees depend on room settings and that user's room role.
## What a Room Contains
| Item | Purpose |
| --- | --- |
| Members | Creator, room admins, members, and guests |
| Playlist | Media items, child lists, and order |
| Current playback | Current media, position, pause state, speed, and version |
| Chat | Room messages controlled by permissions and room switches |
| Join rules | Visibility, password, review requirement, and member limit |
| Permissions | Role defaults and member-level overrides |
| Livestream entry | RTMP/live sessions for the room |
## Who Manages a Room
Platform administrators and room administrators are different roles. A global `root` or `admin` can maintain the instance, but long-term room responsibility should still be represented through room roles. Use member overrides for exceptions.
## Common Room States
| State | User experience | Administration action |
| --- | --- | --- |
| Open to join | Users can enter from the list or invite | Control default permissions and member limits |
| Password required | Users must enter the room password | Rotate leaked passwords |
| Review required | Users wait for approval | Approve or reject with a clear reason |
| Suspended | Users cannot continue joining or operating | Ban the room or close entry points |
## Next Steps
- Users creating or joining rooms: [Create and Join Rooms](../../use/rooms/).
- Managing members and settings: [Room and Member Management](../../admin/rooms-members/).
- Permission details: [Permissions Model](../permissions/) and [Rooms, Permissions, and Preferences](../../use/rooms-permissions/).

@ -87,11 +87,3 @@ Do not use:
| `SYNCTV_BOOTSTRAP_ROOT_USERNAME` | `bootstrap.root_username` |
| `SYNCTV_BOOTSTRAP_ROOT_PASSWORD` | `bootstrap.root_password` |
| `SYNCTV_BOOTSTRAP_ROOT_PASSWORD_FILE` | `bootstrap.root_password` file |
## Continue Reading
- [How Configuration Works](../how-configuration-works/)
- [Security and Secrets](../security/)
- [Production Checklist](../../install/production-checklist/)
- [Docker Compose Deployment](../../install/docker-compose/)
- [Helm Deployment](../../install/helm/)

@ -61,9 +61,3 @@ Decrease it when:
- Audit processing capacity problems should become visible earlier.
For production, keep the default first and use logs or metrics to observe dropped or accumulated audit events.
## Continue Reading
- [Rate Limits and Connection Limits](../rate-limits/)
- [Metrics Monitoring](../metrics/)
- [Configuration Index](../../reference/configuration-index/)

@ -6,7 +6,7 @@ description: Multi-replica coordination, Redis discovery, static peers, Kubernet
import Diagram from '../../../../components/Diagram.astro';
import clusterRuntimeDark from '../../../../assets/diagrams/cluster-runtime-dark.svg';
import clusterRuntimeLight from '../../../../assets/diagrams/cluster-runtime-light.svg';
import { Aside, Card, CardGrid, Steps } from '@astrojs/starlight/components';
import { Aside, Steps } from '@astrojs/starlight/components';
## When to Enable Cluster Mode
@ -46,20 +46,10 @@ cluster:
Cluster mode solves runtime consistency when multiple SyncTV processes serve the same instance. It is not just a load-balancing switch, and it does not replace PostgreSQL, Redis, Ingress, or a deliberate livestream storage/proxy model.
<CardGrid>
<Card title="Single Source of Truth" icon="seti:db">
PostgreSQL stores durable state: users, rooms, permissions, providers, preferences, and audit data. Every node must use the same database.
</Card>
<Card title="Runtime Coordination" icon="setting">
Redis stores ephemeral shared state: node registration, pub/sub, Redis Stream catch-up, leader election, rate limits, and short-lived auth state.
</Card>
<Card title="Inter-Node Trust" icon="setting">
`cluster.secret` authenticates inter-node gRPC calls. It must be identical across replicas and must not be exposed to clients.
</Card>
<Card title="Livestream Reachability" icon="youtube">
RTMP publishers can land on any node, and viewers can hit any node; livestreaming therefore needs a publisher registry, HLS gRPC proxying, and an explicit HLS storage boundary.
</Card>
</CardGrid>
- **Single Source of Truth**: PostgreSQL stores durable state: users, rooms, permissions, providers, preferences, and audit data. Every node must use the same database.
- **Runtime Coordination**: Redis stores ephemeral shared state: node registration, pub/sub, Redis Stream catch-up, leader election, rate limits, and short-lived auth state.
- **Inter-Node Trust**: `cluster.secret` authenticates inter-node gRPC calls. It must be identical across replicas and must not be exposed to clients.
- **Livestream Reachability**: RTMP publishers can land on any node, and viewers can hit any node; livestreaming therefore needs a publisher registry, HLS gRPC proxying, and an explicit HLS storage boundary.
<Diagram
light={clusterRuntimeLight}

@ -472,9 +472,3 @@ synctv --config /etc/synctv/synctv.yaml config validate
```
Validation checks required secrets, cluster Redis requirements, TCP management authentication, CORS origins, gRPC message size, WebAuthn origins, and path resolution.
## Continue Reading
- [Configuration Index](../../reference/configuration-index/): all fields, types, defaults, and detail pages.
- [Environment Variables](../../reference/environment-variables/): supported `SYNCTV_*` variables.
- [How Configuration Works](../how-configuration-works/): precedence, search paths, secret files, and `data_dir` path resolution.

@ -6,7 +6,7 @@ description: RTMP, HLS, HTTP-FLV, pull retry behavior, GOP cache, and livestream
import Diagram from '../../../../components/Diagram.astro';
import livestreamPipelineDark from '../../../../assets/diagrams/livestream-pipeline-dark.svg';
import livestreamPipelineLight from '../../../../assets/diagrams/livestream-pipeline-light.svg';
import { Aside, Card, CardGrid, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
import { Aside, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
## What This Config Controls
@ -25,20 +25,10 @@ Livestreaming includes ingest, realtime packet distribution, FLV playback, HLS r
caption="Livestream data enters through RTMP and StreamHub, then splits by playback protocol: HTTP-FLV streams low-latency chunks, while HLS remuxing writes playlist and segment state to the selected HLS backend."
/>
<CardGrid>
<Card title="RTMP ingest" icon="youtube">
Publishers connect through RTMP. During authentication, the publisher is registered on the local node or shared registry.
</Card>
<Card title="StreamHub" icon="cloud-download">
Live packets are distributed in-process to FLV sessions, the HLS remuxer, and internal relay/pull logic.
</Card>
<Card title="HTTP-FLV" icon="rocket">
Best for low latency. Clients hold long-lived responses, and write timeouts protect the server from slow readers.
</Card>
<Card title="HLS" icon="seti:folder">
Best for broad player compatibility and shared storage/CDN-like deployments. It has higher latency but scales well across replicas.
</Card>
</CardGrid>
- **RTMP ingest**: Publishers connect through RTMP. During authentication, the publisher is registered on the local node or shared registry.
- **StreamHub**: Live packets are distributed in-process to FLV sessions, the HLS remuxer, and internal relay/pull logic.
- **HTTP-FLV**: Best for low latency. Clients hold long-lived responses, and write timeouts protect the server from slow readers.
- **HLS**: Best for broad player compatibility and shared storage/CDN-like deployments. It has higher latency but scales well across replicas.
## Choosing a Playback Protocol

@ -30,9 +30,7 @@ media_providers:
Remote provider instances are not configured in this YAML object. They are persisted through the management API/CLI and only store connection details that SyncTV needs to reach the remote provider, such as `endpoint`, `tls`, `jwt_secret`, `custom_ca`, `timeout`, `insecure_tls`, and `providers`. The remote provider's own Alist, Emby, or Bilibili configuration belongs in the remote provider deployment.
For scenario-based setup guidance for Alist, Emby/Jellyfin, Bilibili, direct URLs, RTMP, or remote Providers, start with [Add Media](../../use/media-sources/).
See the [Provider User Guide](../../use/provider-guide/) for binding, resource, and dynamic-playlist capabilities. See the [Provider Development Guide](../../develop/provider-development/) for implementation and extension workflows.
Create remote Provider instances through the management API or CLI, and keep Alist, Emby/Jellyfin, Bilibili, and other upstream configuration in the matching Provider service. See [Provider Management](../../admin/providers/) for enable, reconnect, and credential maintenance tasks. See [Provider Development](../../develop/provider-development/) to implement or extend a Provider.
## Provider Instances
@ -127,11 +125,3 @@ security:
```
Without a stable credential encryption key, creating or updating encrypted provider credentials may fail, and previously encrypted credentials may become unreadable if the key is lost.
## Continue Reading
- [Add Media](../../use/media-sources/)
- [Provider User Guide](../../use/provider-guide/)
- [Provider Development Guide](../../develop/provider-development/)
- [Playback and Proxy Model](../../use/playback-and-proxy/)
- [Security Hardening and Rotation](../../operations/security-hardening-and-rotation/)

@ -96,9 +96,3 @@ Longer does not mean safer. Public IDs are not authorization. Access control mus
| --- | --- |
| `SYNCTV_PUBLIC_IDS_SQIDS_ALPHABET` | `public_ids.sqids.alphabet` |
| `SYNCTV_PUBLIC_IDS_SQIDS_MIN_LENGTH` | `public_ids.sqids.min_length` |
## Continue Reading
- [How Configuration Works](../how-configuration-works/)
- [Configuration Index](../../reference/configuration-index/)
- [Security and Secrets](../security/)

@ -3,7 +3,7 @@ title: Cache Consistency Development Guide
description: Maintain the strong-consistency protocol for SyncTV server-side L1 caches, Redis L2 caches, and Redis version fences.
---
This page is for developers maintaining server-side cache code. It defines which paths require strong consistency, how Redis version fences act as authoritative freshness boundaries, and what rules new caches must follow.
Server-side caching combines in-process L1 caches, Redis L2 caches, and Redis version fences. The rules below define strongly consistent paths, freshness boundaries, and requirements for new caches.
Core rule: **asynchronous invalidation is for convergence, not correctness**. Authorization, access control, room settings, playback state, membership, and resource-existence paths must remain correct even when a node has not received an invalidation event.

@ -17,9 +17,9 @@ For a minimal runnable call chain, see [SDK and API Examples](../sdk-and-api-exa
| --- | --- | --- |
| Sign in and keep a session | Login, handle MFA, store access/refresh tokens, refresh sessions, handle 401 | This page: “Token Usage” and “Local Login and MFA” |
| Enter room realtime state | Fetch the room, create a WebSocket ticket, connect `/ws/rooms/{roomId}`, decode protobuf | [Realtime API](../realtime-api/) |
| Show synchronized playback | Read current playback state, fetch playback, observe `playbackState` and `playback` | [Playback Model](../../concepts/playback-model/) |
| Add media | Choose Provider, browse or search media, submit playlist item, handle Provider errors | [Media Sources](../../concepts/media-providers/) |
| Handle URL expiry | Read `expires_at`, refresh playback before expiry, discard old URLs after media switch | [Playback and Proxy Model](../../use/playback-and-proxy/) |
| Show synchronized playback | Read current playback state, fetch playback, observe `playbackState` and `playback` | [Playback and Proxy Protocol](../playback-and-proxy/) |
| Add media | Choose Provider, browse or search media, submit playlist item, handle Provider errors | [Media Provider Configuration](../../configuration/media-providers/) |
| Handle URL expiry | Read `expires_at`, refresh playback before expiry, discard old URLs after media switch | [Playback and Proxy Protocol](../playback-and-proxy/) |
| Reconnect | Request a new ticket, reconnect, observe resources with local versions | [Realtime API](../realtime-api/) |
| Build unified errors | Classify by HTTP status, business code, `requestId`, and `Retry-After` | [Errors](../../reference/errors/) |
@ -418,5 +418,5 @@ Handle errors by category, not by exact text:
- [Realtime API](../realtime-api/): WebSocket protobuf, resource observation, version synchronization, and reconnect handling.
- [Errors](../../reference/errors/): HTTP/gRPC/Realtime/Provider error structures and codes.
- [Authentication and Security Model](../../admin/authentication-security/): 2FA, OAuth2, token context, and provider header boundaries.
- [Rooms, Permissions, and Preferences](../../use/rooms-permissions/): roles, permission bits, room settings, and user preferences.
- [Roles, Permissions, and Preferences](../../admin/permissions/): roles, permission bits, room settings, and user preferences.
- [Troubleshooting](../../operations/troubleshooting/): CORS, WebSocket, login, provider, and Range diagnostics.

@ -1,93 +0,0 @@
---
title: Documentation Style Guide
description: SyncTV documentation rules for information architecture, page types, wording, links, terminology, and locale mirrors.
---
SyncTV docs are organized by reader task. Before writing, decide who the reader is, what they need to finish, and how they can verify the result. Do not mix concepts, step-by-step procedures, field references, and troubleshooting matrices in one page.
## Page Types
| Type | Purpose | Write it as |
| --- | --- | --- |
| Task | Help a reader complete one action | Prerequisites, steps, validation, failure handling |
| Concept | Explain a product model or system responsibility | Objects, relationships, responsibilities, and next steps |
| Reference | Look up fields, commands, metrics, or errors | Stable, searchable structure; no teaching burden |
| Troubleshooting | Diagnose by symptom | Symptom, check first, owner, next step |
| Runbook | Admin or operator procedure | Impact, operation order, rollback, validation |
## Opening Paragraph
Start by saying what the page helps the reader do. Avoid generic background.
Use:
```md
This page explains how to create a room, configure join rules, and verify access with a normal member account.
```
Avoid:
```md
This section provides a comprehensive overview of room capabilities and complex boundaries.
```
## Titles
- Task pages use actions: `Create and Join Rooms`, `Add Media`.
- Concept pages use nouns: `Playback Model`, `Permissions Model`.
- Reference pages name the object: `Runtime Settings Reference`, `Metrics Catalog`.
- Do not use vague labels such as “complete guide” or “best practices”.
## Wording
Prefer short sentences and concrete actions.
| Avoid overusing | Prefer |
| --- | --- |
| should normally confirm | check |
| Related Pages | Next steps, Reference, Continue troubleshooting |
| semantics | meaning, impact, rule |
| boundary | responsibility, scope, limitation |
| production rules | before production, operation rules |
These words are not banned. Configuration, security, and architecture pages may need them. Do not use them as a page template.
## Links
- Put links where the reader needs the next step.
- Task pages should end with “Next steps”, not a generic link pile.
- Reference pages can keep reference links, but each link should have a clear purpose.
- Do not use old `deployment/` or `guides/` routes.
- Avoid fragile anchor links into long pages; prefer links to dedicated pages.
## Terminology
| Concept | Chinese | English |
| --- | --- | --- |
| Provider | Provider or 媒体源 Provider | Provider |
| Realtime | Realtime or 实时连接 | Realtime |
| runtime settings | runtime settings or 运行设置 | runtime settings |
| management gRPC | management gRPC or 管理控制面 | management gRPC |
| proxy slice cache | proxy slice cache | proxy slice cache |
Define a term on first use, then keep the same name in that page.
## Locale Mirrors
Every Chinese page must have an English mirror under `en/` with the same path. English pages should be rewritten for English product docs, not translated sentence by sentence.
- Use short sentences.
- Use action titles or clear nouns.
- Avoid abstract nouns when a concrete action works.
- Keep product names stable across locales.
## Validation
Run before submitting docs:
```bash
cd docs
npm run validate
```
Validation checks internal links, Starlight icons, removed routes, retired titles, unfinished-work markers, and English mirrors. Generic related-page endings are reported as warnings and should be cleaned up over time.

@ -3,7 +3,7 @@ title: Implementation Contracts
description: Maintenance rules for transport layers, Provider playback, read replicas, file storage, and playback background workers.
---
This page records implementation contracts that affect correctness across modules. Read it before changing HTTP/gRPC handlers, Provider playback generation, playback workers, read-replica routing, file storage, or SQLx queries.
These contracts govern cross-module behavior in HTTP/gRPC handlers, Provider playback generation, playback workers, read-replica routing, file storage, and SQLx queries.
## Transport and Impl Layers

@ -422,7 +422,7 @@ Rendering only proves syntax and templates are valid. Still run SyncTV config va
- When changing runtime surfaces, dependencies, provider/proxy boundaries, or cluster behavior, update [Architecture Overview](../../overview/architecture/).
- When changing login, 2FA, OAuth2, token, management, or permission boundaries, update [Authentication and Security Model](../../admin/authentication-security/).
- When changing users, rooms, reviews, providers, runtime settings, or management CLI semantics, update [Administer SyncTV](../../admin/).
- When changing room roles, permission bits, room settings, member overrides, or user preferences, update [Rooms, Permissions, and Preferences](../../use/rooms-permissions/).
- When changing room roles, permission bits, room settings, member overrides, or user preferences, update [Roles, Permissions, and Preferences](../../admin/permissions/).
- When changing hot-reload fields registered in `SettingsRegistry`, update [Runtime Settings Reference](../../reference/runtime-settings/).
- When changing the OpenAPI feature, Swagger UI path, or OpenAPI JSON path, update [OpenAPI Access](../../reference/openapi/).
- When changing cluster, admin, or service protobuf files, update [gRPC Debugging](../../reference/grpc/).

@ -1,5 +1,5 @@
---
title: Playback and Proxy Model
title: Playback and Proxy Protocol
description: SyncTV playbacks, playback URLs, Provider headers, proxy modes, Range, slice cache, WebRTC, and livestream boundaries.
---
@ -111,10 +111,3 @@ WebRTC configuration is in [WebRTC Configuration](../../configuration/webrtc/).
| Proxy only fails | Server-to-upstream network or headers | DNS, server network, proxy headers |
| Multi-replica live randomly fails | HLS storage model | Publisher node, shared storage, OSS, gRPC proxy |
| URL stops working later | `expires_at` | Observe or fetch a new playback |
## Continue Reading
- [Add Media](../media-sources/)
- [Client Integration Guide](../../develop/client-integration/)
- [Realtime API](../../develop/realtime-api/)
- [Capacity Planning](../../operations/capacity-planning/)

@ -5,7 +5,7 @@ description: Add a Provider from its upstream client through Core, public APIs,
import { Aside, Steps } from '@astrojs/starlight/components';
Use this guide when adding a Provider or extending an existing one. Each Provider keeps its own protocol model, capabilities, and product workflow while sharing stable SyncTV core contracts.
A Provider implementation spans the upstream protocol, Core model, public APIs, remote transport, CLI, App, and tests. Each Provider keeps its own protocol model and capabilities while sharing stable SyncTV core contracts.
## Design Principles
@ -281,5 +281,3 @@ flutter test
- [ ] HTTP, gRPC, OpenAPI, management, and CLI registrations are complete.
- [ ] The App supports binding, capability gating, URL parsing, preview, partial selection, and dynamic-playlist creation.
- [ ] WireMock, Core, API, CLI, Testcontainers, and Flutter tests pass.
Continue with [Implementation Contracts](../implementation-contracts/), [Client Integration](../client-integration/), and the [Provider User Guide](../../use/provider-guide/).

@ -214,9 +214,3 @@ Resource observation errors are returned as `ServerMessage.resourceObserveError`
| Permission, missing resource, or invalid input error | Re-fetch room state and navigate back when needed |
If sending fails or the server closes the connection, do not assume observations remain active. Rebuild all observations after reconnecting.
## Continue Reading
- Resource fields and subscription examples: [Realtime Resource Observation](../realtime-resource-observation/).
- End-to-end client examples: [SDK and API Examples](../sdk-and-api-examples/).
- Unified error handling: [Errors](../../reference/errors/).

@ -1,13 +1,13 @@
---
title: SDK and API Examples
description: Minimal HTTP/OpenAPI, gRPC, WebSocket Realtime, and Provider API examples for SyncTV clients.
description: Working HTTP/OpenAPI, gRPC, WebSocket Realtime, and Provider API examples for SyncTV clients.
---
import { TabItem, Tabs } from '@astrojs/starlight/components';
## Goal
## Request Sequence
These examples form one runnable chain: login, refresh token, create room, create WebSocket ticket, connect Realtime, read playback state, handle errors, and call Providers. Complete fields are defined by OpenAPI JSON and protobuf.
The examples sign in, refresh tokens, create a room, create a WebSocket ticket, connect Realtime, read playback state, handle errors, and call Providers in sequence. OpenAPI JSON and protobuf define the complete fields.
Read [Client Integration Guide](../client-integration/) first for the protocol boundaries.
@ -43,7 +43,7 @@ npx openapi-typescript openapi.json -o synctv-api.d.ts
See [OpenAPI Access](../../reference/openapi/) for details.
## Minimal HTTP Flow
## HTTP Sign-in and Room Creation
<Tabs syncKey="http-api-examples-en">
<TabItem label="OPAQUE login" icon="approve-check-circle">
@ -100,7 +100,7 @@ The ticket is short-lived, one-time, and room-bound.
</TabItem>
</Tabs>
## Minimal Realtime Flow
## Realtime Connection and Subscription
```ts
const ws = new WebSocket(`wss://app.example.com/ws/rooms/${roomId}?ticket=${ticket}`);
@ -211,10 +211,3 @@ See [Errors](../../reference/errors/).
| Create room, add media, update settings | On timeout, read back state before repeating |
| WebSocket reconnect | Create a new ticket and rebuild observations |
| Provider request | Back off upstream failures and distinguish credential expiry |
## Continue Reading
- [Client Integration Guide](../client-integration/)
- [Realtime API](../realtime-api/)
- [Errors](../../reference/errors/)
- [API and Protobuf Evolution](../../reference/api-versioning/)

@ -1,106 +1,55 @@
---
title: SyncTV Documentation
description: Usage, administration, installation, configuration, operations, and client integration documentation for SyncTV.
template: splash
hero:
tagline: A self-hosted synchronized watching app organized around rooms, playback, chat, media sources, and members.
actions:
- text: Use SyncTV
link: use/
icon: rocket
variant: primary
- text: Install SyncTV
link: install/choose-path/
icon: approve-check-circle
- text: Build a Client
link: develop/client-integration/
icon: document
title: SyncTV Server
description: Deploy, configure, and operate SyncTV Server.
tableOfContents: false
---
import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
import LocaleChoiceTracker from '../../../components/LocaleChoiceTracker.astro';
<LocaleChoiceTracker />
<img src="/screenshots/room-macos.png" alt="SyncTV synchronized room playback" />
Rooms are the daily entry point in SyncTV. Users watch, chat, and switch playlists in rooms. Room administrators manage members and permissions. Platform administrators maintain accounts, reviews, Providers, livestreaming, and runtime policy.
These docs are organized by task. Start with “Use SyncTV” for the product experience, “Administer SyncTV” for instance management, “Install and Upgrade” for deployment, and “Develop with SyncTV” for client integration.
Download the native client from [SyncTV App releases](https://github.com/synctv-org/synctv-app/releases/latest).
## Choose a Path
<CardGrid>
<LinkCard
title="Use SyncTV"
href="use/"
description="Sign in, join rooms, synchronize playback, chat, add media, and manage personal settings."
/>
<LinkCard
title="Administer an Instance"
href="admin/"
description="Manage users, rooms, reviews, providers, livestreaming, runtime settings, and maintenance tasks."
/>
<LinkCard
title="Install or Upgrade"
href="install/choose-path/"
description="Choose Compose, source runs, or Helm/Kubernetes and complete production checks."
/>
<LinkCard
title="Build a Client"
href="develop/client-integration/"
description="Use OpenAPI, gRPC, WebSocket Realtime, tickets, playback info, and errors."
/>
</CardGrid>
## Common Tasks
| Goal | Page |
| --- | --- |
| Sign in and protect an account | [Sign In and Account Security](use/accounts-security/) |
| Create or join a room | [Create and Join Rooms](use/rooms/) |
| Fix playback drift or failure | [Synchronized Playback](use/synchronized-playback/) and [User Troubleshooting](use/troubleshooting/) |
| Add media | [Add Media](use/media-sources/) |
| Manage users, rooms, and reviews | [Administer SyncTV](admin/) |
| Start a self-hosted instance | [Quick Start](install/quick-start/) |
| Build a client | [Client Integration Guide](develop/client-integration/) |
| Join the discussion or see contributors | [Discussion and Contributors](overview/community/) |
## Understand SyncTV
<CardGrid>
<Card title="Rooms" icon="puzzle">
Members, playlists, chat, permissions, and current playback state are organized around rooms. See [Rooms](concepts/rooms/).
</Card>
<Card title="Synchronized Playback" icon="youtube">
The server owns room playback state. Clients follow play, pause, seek, and media changes through Realtime. See [Playback Model](concepts/playback-model/).
</Card>
<Card title="Media Sources" icon="cloud-download">
Providers turn Alist, Emby/Jellyfin, Bilibili, direct URLs, remote services, or live inputs into playable results. See [Media Sources](concepts/media-providers/).
</Card>
<Card title="Permissions" icon="seti:lock">
Global roles, room roles, member overrides, and room settings decide what each person can do. See [Permissions Model](concepts/permissions/).
</Card>
</CardGrid>
## Before Production
<CardGrid>
<Card title="Production Checklist" icon="approve-check-circle">
Confirm TLS, secrets, PostgreSQL, Redis, backups, metrics, management access, and restore practice.
</Card>
<Card title="Runtime Boundaries" icon="setting">
Understand PostgreSQL, Redis, secrets, management endpoints, media proxying, and non-goals.
</Card>
<Card title="Configuration Entry" icon="document">
Configuration files, environment variables, runtime settings, and CLI overrides have different scopes.
</Card>
</CardGrid>
For deployment paths, see [Choose a Deployment Path](install/choose-path/). For runtime dependencies and non-goals, see [Runtime Boundaries](concepts/runtime-boundaries/). For all configuration fields, see [Configuration Index](reference/configuration-index/).
## License
SyncTV is licensed under the MIT License. See the repository `LICENSE` file for the full terms.
<p class="docs-home-lead">
Use Docker Compose on a single host or Helm in an existing Kubernetes cluster. Then configure public access, durable secrets, backups, and monitoring.
</p>
<div class="docs-directory">
<section>
<h2>Deploy</h2>
<ul class="docs-link-list">
<li><a href="install/quick-start/"><strong>Install with Docker Compose</strong><span>Server, NAS, or virtual machine</span></a></li>
<li><a href="install/helm/"><strong>Install with Helm</strong><span>Kubernetes, Ingress, and multiple replicas</span></a></li>
<li><a href="operations/upgrades/"><strong>Upgrade an installation</strong><span>Backup, migrate, and roll back</span></a></li>
<li><a href="install/production-checklist/"><strong>Production checklist</strong><span>TLS, secrets, data, and monitoring</span></a></li>
</ul>
</section>
<section>
<h2>Configure</h2>
<ul class="docs-link-list">
<li><a href="configuration/how-configuration-works/"><strong>Loading and precedence</strong><span>YAML, environment variables, and secret files</span></a></li>
<li><a href="configuration/full-example/"><strong>Configuration examples</strong><span>Minimal production config and full field template</span></a></li>
<li><a href="configuration/security/"><strong>Security and secrets</strong><span>JWT, OPAQUE, CORS, and credential encryption</span></a></li>
<li><a href="reference/configuration-index/"><strong>Configuration fields</strong><span>Types, defaults, and restart requirements</span></a></li>
</ul>
</section>
<section>
<h2>Administer and operate</h2>
<ul class="docs-link-list">
<li><a href="admin/"><strong>Administer SyncTV</strong><span>Users, rooms, permissions, and Providers</span></a></li>
<li><a href="operations/observability/"><strong>Monitoring and runbooks</strong><span>Health, metrics, logs, and alerts</span></a></li>
<li><a href="operations/backup-restore/"><strong>Backup and restore</strong><span>PostgreSQL, secrets, and recovery drills</span></a></li>
<li><a href="operations/troubleshooting/"><strong>Troubleshoot</strong><span>Errors, status codes, and runtime signals</span></a></li>
</ul>
</section>
<section>
<h2>Develop and reference</h2>
<ul class="docs-link-list">
<li><a href="develop/local-development/"><strong>Local development</strong><span>Dependencies, databases, tests, and code generation</span></a></li>
<li><a href="reference/cli/"><strong>CLI</strong><span>Service control and administration commands</span></a></li>
<li><a href="reference/openapi/"><strong>OpenAPI</strong><span>HTTP API specification and client generation</span></a></li>
<li><a href="reference/grpc/"><strong>gRPC</strong><span>Public API, management API, and reflection</span></a></li>
</ul>
</section>
</div>

@ -1,75 +1,32 @@
---
title: Choose a Deployment Path
description: Choose between single-node production Compose, local evaluation, source runs, and Helm/Kubernetes.
title: Choose a Deployment
description: Compare the infrastructure and operating requirements of Docker Compose and Helm.
---
import { Aside, Steps } from '@astrojs/starlight/components';
import Diagram from '../../../../components/Diagram.astro';
import deploymentPathDark from '../../../../assets/diagrams/deployment-path-dark.svg';
import deploymentPathLight from '../../../../assets/diagrams/deployment-path-light.svg';
Docker Compose covers most self-hosted installations. Helm is for platforms that already run Kubernetes, Ingress, and centralized secret management.
## Paths
<table class="deployment-matrix">
<thead><tr><th>Requirement</th><th>Docker Compose</th><th>Helm</th></tr></thead>
<tbody>
<tr><td>Environment</td><td>One Linux server, NAS, or virtual machine</td><td>Existing Kubernetes cluster</td></tr>
<tr><td>SyncTV replicas</td><td>One</td><td>One or more</td></tr>
<tr><td>PostgreSQL / Redis</td><td>Started by Compose</td><td>In-cluster or managed services</td></tr>
<tr><td>TLS entry point</td><td>Existing reverse proxy</td><td>Ingress Controller</td></tr>
<tr><td>Secrets</td><td>Local env files</td><td>Kubernetes Secret or an external secret system</td></tr>
<tr><td>Installation</td><td><a href="../quick-start/">Docker Compose</a></td><td><a href="../helm/">Helm</a></td></tr>
</tbody>
</table>
Use **single-node production Compose** for a long-running instance on one machine. Switch paths only for source changes, temporary local evaluation, or an existing Kubernetes platform.
Use the [local development environment](../../develop/local-development/) for source changes. Its Compose file starts development dependencies only.
<Diagram
light={deploymentPathLight}
dark={deploymentPathDark}
alt="SyncTV deployment path decision diagram choosing single-node production Compose, local evaluation, source run, or Helm based on long-running service, source work, and Kubernetes multi-replica needs."
caption="Decide the operating goal first, then open the matching deployment guide."
/>
## Production Requirements
## Decision Table
Complete these items before serving production traffic:
| Path | Best for | Startup style | Production fit | Next page |
| --- | --- | --- | --- | --- |
| Single-node production Compose | Self-hosters, small teams, one server | Prebuilt image + `.env.postgres` + `.env.redis` + `.env.synctv` | Default production path | [Quick Start](../../install/quick-start/) |
| Local evaluation | Temporary UI or feature preview | `docker-compose.dev.yml` | Not for public or long-running use | [Development Environment](../../develop/local-development/) |
| Source run | Developers, API debugging, code changes | Container dependencies + local `cargo +nightly run` | Not a deployment path | [Development Guide](../../develop/local-development/) |
| Helm/Kubernetes | Multi-replica or platform teams | Helm values + Kubernetes Secret/PVC/Ingress | Production capable, higher complexity | [Helm Deployment](../helm/) |
- Persistent PostgreSQL data and tested backups.
- Durable JWT, OPAQUE, and credential-encryption secrets.
- HTTPS on public entry points.
- Shared PostgreSQL, Redis, and cluster secrets for multiple replicas.
- A backup and migration check before upgrades.
## Single-Node Production Compose
Choose it if any of these are true:
- You have one server, NAS, or VM.
- You want the shortest path to a long-running SyncTV instance.
- You do not want to start with Kubernetes, Ingress controllers, PVCs, or Secret operators.
- You can manage PostgreSQL backups and a few long-lived secrets.
Success signals:
- `.env.postgres`, `.env.redis`, and `.env.synctv` are persisted and backed up.
- `make compose-config` passes.
- `/health/ready` returns 200.
- The root user can log in.
- PostgreSQL has a backup plan.
Execution path:
1. [Quick Start](../../install/quick-start/): download Compose files, generate env files, set the root password, and start the service.
2. [Docker Compose Deployment](../docker-compose/): review production Compose, development Compose, volumes, and ports.
3. [Production Checklist](../production-checklist/): verify TLS, secrets, backups, metrics, alerts, and upgrade strategy.
## Exception Paths
| Scenario | Path | Boundary |
| --- | --- | --- |
| Temporary evaluation | Local evaluation | Fast startup with generated local env files; keep it off the public internet and do not run it long term. |
| Source changes | Source run | PostgreSQL and Redis can come from development Compose while SyncTV runs from the local Rust toolchain. |
| Existing Kubernetes platform | Helm | Decide HTTP/gRPC Ingress, Secret, PVC, metrics, Redis, HLS storage, and rolling updates first. |
| Multi-replica realtime | Helm or self-managed multi-replica | All replicas must share PostgreSQL, Redis, `redis.key_prefix`, and `cluster.secret`. |
## Decision Rules
<Steps>
1. If it faces users, do not use development Compose.
2. If it runs long term, back up PostgreSQL and production secrets.
3. If it runs multiple replicas, share PostgreSQL, Redis, `redis.key_prefix`, and `cluster.secret`.
4. If HLS runs across replicas, choose publisher-node proxying, `shared_file`, or OSS explicitly.
5. If the management plane uses TCP, configure a token and keep it away from normal public entrypoints.
</Steps>
<Aside type="tip">
When unsure, choose single-node production Compose. It is the smallest production loop and can still be migrated to Helm or another orchestrator later.
</Aside>
The [Production Checklist](../production-checklist/) contains the full set of checks. Follow [Upgrades and Migrations](../../operations/upgrades/) for an existing installation.

@ -98,11 +98,3 @@ kubectl -n synctv get pods
| Test environment | Target version has started in a test environment with migrations, login, room reads/writes, and Provider access verified. |
| Rolling update | `server.shutdown_drain_timeout_seconds` is lower than Kubernetes termination grace period. |
| Rollback | Rollback version, database state, and config source are known. |
## Continue Reading
- [Backup and Restore](../../operations/backup-restore/)
- [Observability Runbook](../../operations/observability/)
- [Capacity Planning](../../operations/capacity-planning/)
- [Security Hardening and Rotation](../../operations/security-hardening-and-rotation/)
- [Upgrades and Migrations](../../operations/upgrades/)

@ -1,6 +1,6 @@
---
title: Quick Start
description: Start a single-node SyncTV deployment with Docker Compose and verify it is running.
title: Install with Docker Compose
description: Start SyncTV, PostgreSQL, and Redis on one host and verify service readiness.
---
import { Aside, Code, Steps } from '@astrojs/starlight/components';
@ -9,16 +9,16 @@ import {
githubCloneUrl,
} from '../../../../lib/project';
This path is for single-node production: one SyncTV process, one PostgreSQL instance, and one Redis instance. For Kubernetes or multiple replicas, complete this path first, then read [Helm Deployment](../../install/helm/) and [Cluster Configuration](../../configuration/cluster/).
This installation runs SyncTV, PostgreSQL, and Redis on one host. For Kubernetes, use the [Helm installation](../../install/helm/).
## Prerequisites
- Docker and Docker Compose are available.
- GNU Make and `openssl` are available for the env initializer.
- The current directory can permanently store Compose files, `.env.postgres`, `.env.redis`, `.env.synctv`, and volumes.
- You have an initial root password. Use a password manager in production.
- A durable working directory for the Compose files, three env files, and data volumes.
- An initial root password generated by a password manager.
## Start
## Install
<Steps>
1. Get the production Compose configuration:
@ -40,13 +40,13 @@ This path is for single-node production: one SyncTV process, one PostgreSQL inst
SYNCTV_BOOTSTRAP_ROOT_PASSWORD=replace-with-a-strong-password
```
4. Check the rendered Compose config:
4. Validate the rendered Compose config:
```bash
make compose-config
```
5. Start the service:
5. Start the services in the background:
```bash
make compose-up
@ -55,20 +55,24 @@ This path is for single-node production: one SyncTV process, one PostgreSQL inst
## Verify
Inspect the containers and request the readiness endpoint:
```bash
make compose-ps
curl -fsS http://localhost:8080/health/ready
```
Then open:
After the readiness request succeeds, open:
```text
http://localhost:8080
```
The default root username is `root`. Its password comes from `SYNCTV_BOOTSTRAP_ROOT_PASSWORD` in `.env.synctv`.
Sign in as `root` with the `SYNCTV_BOOTSTRAP_ROOT_PASSWORD` value from `.env.synctv`.
## Back Up Data and Secrets
## Values To Keep
Back up PostgreSQL and store these values in a password manager or secret management system:
| Environment variable | Purpose |
| --- | --- |
@ -78,7 +82,7 @@ The default root username is `root`. Its password comes from `SYNCTV_BOOTSTRAP_R
| `SYNCTV_BOOTSTRAP_ROOT_PASSWORD` | Creates the initial root user |
<Aside type="caution">
Do not delete or regenerate the long-lived secrets in `.env.synctv`. Changing `SYNCTV_SECURITY_OPAQUE_SERVER_SETUP_SECRET` or `SYNCTV_SECURITY_CREDENTIAL_ENCRYPTION_KEY` can make existing password records or Provider credentials unusable.
Keep the secrets in `.env.synctv` for the lifetime of the installation. Existing password records depend on the OPAQUE secret, and Provider credentials depend on the credential encryption key.
</Aside>
## Common Failures
@ -90,8 +94,8 @@ Do not delete or regenerate the long-lived secrets in `.env.synctv`. Changing `S
| Browser CORS errors | Set `SYNCTV_SERVER_CORS_ALLOWED_ORIGINS` in `.env.synctv`; use origins only. |
| Root user cannot log in | Confirm `SYNCTV_BOOTSTRAP_ROOT_PASSWORD` was set before first database startup and inspect bootstrap logs. |
## Continue Reading
## Before Production Traffic
- Complete the [Production Checklist](../../install/production-checklist/) for TLS, backups, metrics, and alerts.
- Read <a href={englishComposeDeploymentDocsUrl}>Docker Compose Deployment</a> for Compose file, port, and volume details.
- For local source development, read [Development Guide](../../develop/local-development/).
- The <a href={englishComposeDeploymentDocsUrl}>Docker Compose reference</a> lists ports, volumes, and maintenance commands.
- [Upgrades and Migrations](../../operations/upgrades/) covers release upgrades.

@ -148,10 +148,3 @@ Redis loss does not usually destroy durable business data, but it changes short-
- Cluster nodes must register and catch up again.
If strong token revocation is required, use highly available Redis and keep token lifetimes short.
## Continue Reading
- [Security Hardening and Rotation](../security-hardening-and-rotation/)
- [Upgrades and Migrations](../upgrades/)
- [Production Checklist](../../install/production-checklist/)
- [Troubleshooting](../troubleshooting/)

@ -118,10 +118,3 @@ Metric names are listed in [Metrics Catalog](../../reference/metrics-catalog/).
Deploy while WebSocket and live connections exist; confirm readiness removes traffic and drain time is enough.
</TabItem>
</Tabs>
## Continue Reading
- [Observability Runbook](../observability/)
- [Rate Limits and Connection Limits](../../configuration/rate-limits/)
- [Playback and Proxy Model](../../use/playback-and-proxy/)
- [Cluster Configuration](../../configuration/cluster/)

@ -120,12 +120,3 @@ Metrics:
- Do not expose `/metrics` publicly.
- Inject metrics bearer tokens or Basic passwords through secrets.
- Metrics should describe capacity, error rates, connection counts, and latency. They should not contain user content.
## Continue Reading
- [Backup and Restore](../backup-restore/)
- [Upgrades and Migrations](../upgrades/)
- [Observability Runbook](../observability/)
- [Authentication and Security Model](../../admin/authentication-security/)
- [Rooms, Permissions, and Preferences](../../use/rooms-permissions/)
- [Runtime Settings Reference](../../reference/runtime-settings/)

@ -1,6 +1,6 @@
---
title: Runtime Boundaries
description: PostgreSQL, Redis, secrets, management endpoints, metrics, media proxying, and SyncTV non-goals.
title: Deployment and Runtime Boundaries
description: PostgreSQL, Redis, secrets, management endpoints, metrics, media proxying, and production deployment boundaries.
---
SyncTV is an application service. It is not a database, object store, media library, CDN, or public management platform. Confirm these boundaries before production deployment.

@ -3,7 +3,7 @@ title: Observability Runbook
description: SyncTV health checks, metrics, logs, key monitoring signals, and incident data collection.
---
import { Card, CardGrid, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
import { Steps, TabItem, Tabs } from '@astrojs/starlight/components';
## Goals
@ -84,20 +84,10 @@ Notes:
## Key Signals
<CardGrid>
<Card title="Dependencies" icon="seti:db">
PostgreSQL connectivity, pool exhaustion, Redis connectivity, Redis latency, and Redis key-prefix collisions.
</Card>
<Card title="Authentication" icon="approve-check-circle">
Login failures, MFA failures, email send failures, OAuth2 state errors, and brute-force lockouts.
</Card>
<Card title="Realtime" icon="puzzle">
WebSocket connections, per-user/per-room limits, message rate limiting, and reconnect spikes.
</Card>
<Card title="Media" icon="youtube">
Provider error rate, upstream timeouts, proxy bypass, slice-cache hit rate, Range anomalies, and livestream retries.
</Card>
</CardGrid>
- **Dependencies**: PostgreSQL connectivity, pool exhaustion, Redis connectivity, Redis latency, and Redis key-prefix collisions.
- **Authentication**: Login failures, MFA failures, email send failures, OAuth2 state errors, and brute-force lockouts.
- **Realtime**: WebSocket connections, per-user/per-room limits, message rate limiting, and reconnect spikes.
- **Media**: Provider error rate, upstream timeouts, proxy bypass, slice-cache hit rate, Range anomalies, and livestream retries.
## Alert Starting Points
@ -154,13 +144,3 @@ kubectl -n synctv rollout history deploy/synctv
</TabItem>
</Tabs>
## Continue Reading
- Startup or configuration failures: [Troubleshooting](../troubleshooting/).
- Capacity, connections, database, Redis, or media bandwidth planning: [Capacity Planning](../capacity-planning/).
- Metric names and groups: [Metrics Catalog](../../reference/metrics-catalog/).
- Launch checks: [Production Checklist](../../install/production-checklist/).
- Data recovery: [Backup and Restore](../backup-restore/).
- Releases: [Upgrades and Migrations](../upgrades/).
- Metrics configuration: [Metrics Monitoring](../../configuration/metrics/).

@ -114,10 +114,3 @@ If it leaks:
| Logs | JSON logs without secrets, cookies, or JWTs |
| Metrics | No public exposure; use bearer or platform auth |
| Backups | Back up and restore database and secrets together |
## Continue Reading
- [Security and Secrets](../../configuration/security/)
- [Authentication and Security Model](../../admin/authentication-security/)
- [Backup and Restore](../backup-restore/)
- [Errors](../../reference/errors/)

@ -101,7 +101,7 @@ Range-capable upstreams usually return `206 Partial Content`. If they return `20
| Configuration | Effective config, secrets, environment overrides, `*_file` paths | [How Configuration Works](../../configuration/how-configuration-works/) |
| Deployment | Compose env, Helm values, Services, Ingresses, Secret keys | [Docker Compose](../../install/docker-compose/), [Helm](../../install/helm/) |
| Authentication | SMTP, OAuth2 redirect, WebAuthn origin, 2FA, rate limits | [Security Model](../../admin/authentication-security/), [Email and OAuth2](../../configuration/email-oauth2/), [WebAuthn](../../configuration/webauthn/) |
| Media | Provider headers, Range, proxy, slice cache, HLS backend | [Playback and Proxy Model](../../use/playback-and-proxy/) |
| Media | Provider headers, Range, proxy, slice cache, HLS backend | [Playback and Proxy Protocol](../../develop/playback-and-proxy/) |
| Capacity | WebSocket, database pool, Redis, Provider, proxy bandwidth, livestreaming | [Capacity Planning](../capacity-planning/), [Metrics Catalog](../../reference/metrics-catalog/) |
## Collect

@ -10,7 +10,7 @@ import kubernetesTopologyDark from '../../../../assets/diagrams/kubernetes-topol
import kubernetesTopologyLight from '../../../../assets/diagrams/kubernetes-topology-light.svg';
import productionMinimalDark from '../../../../assets/diagrams/production-minimal-dark.svg';
import productionMinimalLight from '../../../../assets/diagrams/production-minimal-light.svg';
import { Aside, Card, CardGrid, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
import { Aside, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
## Start With the Model
@ -44,20 +44,10 @@ PostgreSQL is durable business state. Redis is shared short-lived state and coor
## Major Components
<CardGrid>
<Card title="API and realtime" icon="document">
HTTP REST, public gRPC, WebSocket, and room realtime events share the same business services and permission model.
</Card>
<Card title="Authentication" icon="approve-check-circle">
Password, OPAQUE, passkey/WebAuthn, email codes, OAuth2, user-level 2FA, and JWT tokens make up the login layer.
</Card>
<Card title="Media" icon="puzzle">
Providers resolve external media, the proxy performs controlled forwarding, and slice cache stores Range slices only.
</Card>
<Card title="Horizontal scaling" icon="cloud-download">
Multi-node deployments use Redis, discovery, leader election, and transactional outbox delivery boundaries.
</Card>
</CardGrid>
- **API and realtime**: HTTP REST, public gRPC, WebSocket, and room realtime events share the same business services and permission model.
- **Authentication**: Password, OPAQUE, passkey/WebAuthn, email codes, OAuth2, user-level 2FA, and JWT tokens make up the login layer.
- **Media**: Providers resolve external media, the proxy performs controlled forwarding, and slice cache stores Range slices only.
- **Horizontal scaling**: Multi-node deployments use Redis, discovery, leader election, and transactional outbox delivery boundaries.
## Runtime Surfaces
@ -167,12 +157,3 @@ Kubernetes multi-replica topology:
alt="Kubernetes multi-replica topology showing HTTP Ingress, gRPC Ingress, separate Services, multiple SyncTV pods, PostgreSQL, Redis, HLS backend or publisher-node proxy, and external media providers."
caption="Kubernetes multi-replica deployments should split HTTP and gRPC Services/Ingresses and connect every pod to the same PostgreSQL and Redis backends. Local HLS backends use publisher-node proxying; shared_file lets the current node read TS segments from a shared path, and OSS provides object-storage-backed segments."
/>
## Continue Reading
- [Quick Start](../../install/quick-start/)
- [Configuration Index](../../reference/configuration-index/)
- [Production Checklist](../../install/production-checklist/)
- [Backup and Restore](../../operations/backup-restore/)
- [Upgrades and Migrations](../../operations/upgrades/)
- [Observability Runbook](../../operations/observability/)

@ -1,142 +0,0 @@
---
title: Common Workflows
description: Task-oriented SyncTV workflows for users, room administrators, platform administrators, developers, and operators.
---
import { Aside, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
## Choose the Goal
Start from the goal you are handling. These workflows keep the operating order; field, API, and configuration details live in the linked topic pages.
<Aside type="tip">
After the first production deployment, use the launch validation workflow. For support cases, start with the user troubleshooting workflow.
</Aside>
## User Workflows
<Tabs syncKey="user-workflows-en">
<TabItem label="Start watching" icon="youtube">
<Steps>
1. Sign in and confirm email, 2FA, or OAuth2 status.
2. Create a room or open an existing room entry point.
3. Submit a password or join review if the room requires it.
4. Add media or choose an existing playlist item.
5. Start playback if you have permission, otherwise wait for a room administrator.
6. If playback fails, refresh the playback info and check whether proxy playback is required.
</Steps>
</TabItem>
<TabItem label="Enable 2FA" icon="seti:lock">
<Steps>
1. Make sure at least two local factors are available: password, passkey, verified email.
2. Bind a passkey or verify email.
3. Enable 2FA.
4. Sign out and sign in once to verify the second factor.
5. Do not remove factors until at least two local methods remain.
</Steps>
</TabItem>
</Tabs>
## Room Administrator Workflows
### Create a Controlled Room
<Steps>
1. Create a room with a clear name and description.
2. Set a room password if needed.
3. Enable `requireApproval` for semi-public rooms.
4. Set `maxMembers` according to service and upstream Provider capacity.
5. Review member and guest default permissions.
6. Join once with a normal account to validate the path.
</Steps>
### Handle Member Issues
| Goal | Action | Note |
| --- | --- | --- |
| Temporary mute | Remove `send_chat_messages` from the member | Lower impact than disabling chat room-wide |
| Grant playback control | Add `control_playback_state` | Add `navigate_playback` for media switching |
| Remove disruptive member | Kick the member or platform-ban the user | Room ban is not a platform ban |
| Long-term responsibility | Adjust role or defaults | Avoid large stacks of personal overrides |
See [Permissions Model](../../concepts/permissions/) and [Rooms, Permissions, and Preferences](../../use/rooms-permissions/) for details.
## Platform Administrator Workflows
### Launch Validation
<Steps>
1. Follow the [Production Checklist](../../install/production-checklist/) for secrets, database, Redis, TLS, and backups.
2. Run `synctv config validate --strict`.
3. Check `/health/ready`.
4. Sign in as root, create a normal user, and create a test room.
5. Validate WebSocket, chat, playback control, Provider browse, and proxy playback.
6. Enable metrics and confirm scraping.
7. Perform a PostgreSQL and secret restore drill.
</Steps>
### Add a Media Provider
<Steps>
1. Decide between a local Provider and a remote Provider instance.
2. Configure or create the Provider instance and ensure credential encryption is configured.
3. Test login, browse, search, and playback with an administrator.
4. Test both direct and proxy playback.
5. For Range-capable upstreams, verify seek and slice cache behavior.
6. Give users a clear default Provider or usage guidance.
</Steps>
See [Add Media](../../use/media-sources/).
## Developer Workflows
### Bring Up a Client
<Steps>
1. Read [Client Integration Guide](../../develop/client-integration/) for HTTP, gRPC, and WebSocket boundaries.
2. Start the service with OpenAPI and export `/api-docs/openapi.json`.
3. Generate an SDK or write minimal requests.
4. Implement login and refresh token handling.
5. Create a WebSocket ticket and connect to `/ws/rooms/{roomId}`.
6. Use [Realtime API](../../develop/realtime-api/) to observe playback state, playback info, room settings, and members.
7. Handle `status`, `code`, `requestId`, and `Retry-After` using [Errors](../../reference/errors/).
</Steps>
### Add or Change an API
<Steps>
1. Choose HTTP/OpenAPI, gRPC, or Realtime.
2. Update proto or handler while keeping errors and permissions consistent.
3. Add tests and update OpenAPI or protobuf documentation.
4. Update [SDK and API Examples](../../develop/sdk-and-api-examples/), [Realtime API](../../develop/realtime-api/), or [gRPC Debugging](../../reference/grpc/).
5. If protocol behavior changes, update [API and Protobuf Evolution](../../reference/api-versioning/).
</Steps>
## Operator Workflows
### Capacity or Performance Issue
<Steps>
1. Inspect HTTP, WebSocket, database, cache, Provider, livestream, and cluster metrics.
2. Use [Capacity Planning](../../operations/capacity-planning/) to identify connection, database, Redis, Provider, bandwidth, or storage bottlenecks.
3. Reduce upstream pressure with Redis, slice cache, member limits, and connection limits.
4. In multi-replica mode, confirm shared PostgreSQL, Redis, and consistent secrets.
5. Record version, deployment shape, key metrics, and logs before using [Troubleshooting](../../operations/troubleshooting/).
</Steps>
### Rotate Secrets
<Steps>
1. Read [Security Hardening and Rotation](../../operations/security-hardening-and-rotation/).
2. Separate directly rotatable tokens from JWT, OPAQUE setup secret, and credential encryption key.
3. Back up old secrets.
4. Validate login, Provider decryption, WebSocket, OAuth2, and WebAuthn in a test environment.
5. Deploy during a quiet window and watch error rates.
</Steps>
## Continue Reading
- [Use SyncTV](../../use/)
- [Administer SyncTV](../../admin/)
- [SDK and API Examples](../../develop/sdk-and-api-examples/)
- [Observability Runbook](../../operations/observability/)

@ -1,20 +0,0 @@
---
title: Discussion and Contributors
description: Join the SyncTV discussion and see contributors across the server and app projects.
---
This page links to the public SyncTV discussion and recognizes contributors across the server and app projects.
## Join the Discussion
Join the [SyncTV Telegram discussion](https://t.me/synctv) to talk about deployment, operations, playback, media providers, client development, and product ideas.
Messages in the public group are visible to other members. Remove passwords, tokens, cookies, private URLs, and personal data before sharing logs, screenshots, or configuration.
## Contributors
This contributor image combines the `synctv-org/synctv` server and `synctv-org/synctv-app` client repositories.
![SyncTV contributors](https://contrib.nn.ci/api?repo=synctv-org/synctv&repo=synctv-org/synctv-app)
Submit code through the Pull Request workflow in the relevant repository: [SyncTV Server](https://github.com/synctv-org/synctv) or [SyncTV App](https://github.com/synctv-org/synctv-app).

@ -1,88 +0,0 @@
---
title: Documentation Map
description: Role-based and product-task entry points for SyncTV documentation.
---
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
## Start by Role
<CardGrid>
<LinkCard
title="Users"
href="../../use/"
description="Sign in, create or join rooms, synchronize playback, chat, add media, and manage personal settings."
/>
<LinkCard
title="Administrators"
href="../../admin/"
description="Manage users, rooms, members, reviews, Providers, runtime settings, and maintenance."
/>
<LinkCard
title="Deployers"
href="../../install/choose-path/"
description="Choose single-node Compose, source runs, or Helm/Kubernetes and complete launch checks."
/>
<LinkCard
title="Client Developers"
href="../../develop/client-integration/"
description="Use authentication, HTTP/gRPC, WebSocket Realtime, playback info, Provider APIs, and errors."
/>
<LinkCard
title="Operators"
href="../../operations/troubleshooting/"
description="Validate config, observe health, plan capacity, back up, upgrade, rotate secrets, and handle incidents."
/>
<LinkCard
title="Reference Lookup"
href="../../reference/configuration-index/"
description="Look up configuration fields, environment variables, CLI commands, runtime settings, metrics, errors, and limits."
/>
</CardGrid>
## Product Tasks
| Task | Start | Next pages |
| --- | --- | --- |
| Sign in and secure an account | [Sign In and Account Security](../../use/accounts-security/) | [Authentication and Security Model](../../admin/authentication-security/), [WebAuthn and Passkeys](../../configuration/webauthn/) |
| Create or join rooms | [Create and Join Rooms](../../use/rooms/) | [Rooms](../../concepts/rooms/), [Rooms, Permissions, and Preferences](../../use/rooms-permissions/) |
| Configure room permissions | [Permissions Model](../../concepts/permissions/) | [Room and Member Management](../../admin/rooms-members/) |
| Add and play media | [Add Media](../../use/media-sources/) | [Provider User Guide](../../use/provider-guide/), [Playback Model](../../concepts/playback-model/) |
| Enable livestreaming | [Add Media](../../use/media-sources/) | [Livestream Configuration](../../configuration/livestream/) |
| Integrate a client | [Client Integration Guide](../../develop/client-integration/) | [SDK and API Examples](../../develop/sdk-and-api-examples/), [Realtime API](../../develop/realtime-api/) |
| Change shared implementation behavior | [Implementation Contracts](../../develop/implementation-contracts/) | [Cache Consistency Development Guide](../../develop/cache-consistency/), [Playback Background Workers](../../concepts/playback-background-workers/) |
| Add or extend a Provider | [Provider Development Guide](../../develop/provider-development/) | [Implementation Contracts](../../develop/implementation-contracts/), [OpenAPI](../../reference/openapi/), [gRPC](../../reference/grpc/) |
| Support user issues | [User Troubleshooting](../../use/troubleshooting/) | [Troubleshooting](../../operations/troubleshooting/) |
## Install and Maintain
| Goal | Start | Next pages |
| --- | --- | --- |
| Self-host one node | [Quick Start](../../install/quick-start/) | [Docker Compose Deployment](../../install/docker-compose/), [Production Checklist](../../install/production-checklist/) |
| Deploy on Kubernetes | [Helm Deployment](../../install/helm/) | [Cluster Configuration](../../configuration/cluster/), [Observability Runbook](../../operations/observability/) |
| Change configuration | [How Configuration Works](../../configuration/how-configuration-works/) | [Configuration Index](../../reference/configuration-index/), [Environment Variables](../../reference/environment-variables/) |
| Back up and restore | [Backup and Restore](../../operations/backup-restore/) | [Data, Privacy, and Retention](../../operations/data-retention/) |
| Upgrade or release | [Upgrades and Migrations](../../operations/upgrades/) | [Release Process](../../operations/release/) |
| Handle incidents | [Troubleshooting](../../operations/troubleshooting/) | [Metrics Catalog](../../reference/metrics-catalog/), [Capacity Planning](../../operations/capacity-planning/) |
## Configuration Topics
1. [How Configuration Works](../../configuration/how-configuration-works/)
2. [Security and Secrets](../../configuration/security/)
3. [Database and Redis](../../configuration/database-and-redis/)
4. [Server Listener and Runtime Paths](../../configuration/server-and-runtime/)
5. Continue with WebAuthn, email/OAuth2, providers, livestreaming, metrics, and cluster pages as features are enabled.
## Reference Lookup
| Reference | Use |
| --- | --- |
| [Configuration Index](../../reference/configuration-index/) | Static configuration fields |
| [Environment Variables](../../reference/environment-variables/) | Environment variable to config field mapping |
| [Runtime Settings](../../reference/runtime-settings/) | Hot-reloadable database settings |
| [CLI Reference](../../reference/cli/) | Management commands |
| [OpenAPI](../../reference/openapi/) | HTTP API JSON and Swagger UI |
| [gRPC](../../reference/grpc/) | gRPC debugging entrypoint |
| [Metrics Catalog](../../reference/metrics-catalog/) | Prometheus metric names and labels |
| [Errors](../../reference/errors/) | HTTP, gRPC, Realtime, and Provider errors |
| [Limitations and Non-goals](../../reference/limitations/) | Current design boundaries and non-goals |

@ -79,10 +79,3 @@ Realtime changes need special care:
| Realtime messages | Realtime API, SDK examples |
| Configuration field | Configuration index, full example, topic page |
| Operations behavior | Observability, troubleshooting, capacity, rotation |
## Continue Reading
- [Development Environment](../../develop/local-development/)
- [OpenAPI Access](../openapi/)
- [gRPC Debugging](../grpc/)
- [Errors](../errors/)

@ -58,7 +58,7 @@ synctv provider alist --help
Command families and common usage are listed here. Exact flags should be checked with `synctv <command> --help`, because clap help is generated from the current binary.
</Aside>
For operational semantics, read [Administer SyncTV](../../admin/). Before changing room roles, permission bits, room settings, or user preferences, read [Rooms, Permissions, and Preferences](../../use/rooms-permissions/).
See [Administration](../../admin/) for operational semantics and [Roles, Permissions, and Preferences](../../admin/permissions/) for room roles, permission bits, room settings, and user preferences.
## Global Flags

@ -30,7 +30,7 @@ Most fields can keep their defaults. Production launch should prioritize secrets
| `livestream.*` | RTMP/FLV/HLS livestreaming | HLS storage model differs between replicas | Restart required | Use shared filesystem or OSS for high traffic |
| `proxy_slice_cache.*` | Proxy Range slice cache is needed | Expecting full-file cache | Restart required | Mount enough storage; only Range slices are cached |
Shortest verification loop:
Run these checks after changing configuration:
```bash
synctv config validate
@ -71,7 +71,7 @@ Use the field index below for bare-metal, Kubernetes, secret files, or custom YA
| `jwt` | object | see below | [Security and Secrets](../../configuration/security/) |
| `logging` | object | see below | [Server Listener and Runtime Paths](../../configuration/server-and-runtime/) |
| `livestream` | object | see below | [Livestream Configuration](../../configuration/livestream/) |
| `chat` | object | see below | [Chat](../../use/chat/) |
| `chat` | object | see below | `chat` field table on this page |
| `webauthn` | object | see below | [WebAuthn and Passkeys](../../configuration/webauthn/) |
| `email` | object | see below | [Email and OAuth2](../../configuration/email-oauth2/) |
| `media_providers` | object | see below | [Media Providers](../../configuration/media-providers/) |

@ -302,9 +302,3 @@ These variables are read by the `synctv` management CLI and are not service stat
| Environment variable | Meaning |
| --- | --- |
| `SYNCTV_MANAGEMENT_ENDPOINT` | Management endpoint used by CLI commands, for example `unix:///var/lib/synctv/run/synctv.sock` or `http://127.0.0.1:50052` |
## Continue Reading
- [How Configuration Works](../../configuration/how-configuration-works/)
- [Full Configuration Example](../../configuration/full-example/)
- [Configuration Index](../configuration-index/)

@ -3,7 +3,6 @@ title: Errors
description: SyncTV HTTP, gRPC, Realtime, Provider, and operations error response shapes, codes, status mapping, and client handling guidance.
---
import { Card, CardGrid } from '@astrojs/starlight/components';
## HTTP Error Response
@ -126,23 +125,7 @@ Resource observation errors do not necessarily close the connection.
## Client Rules
<CardGrid>
<Card title="Classify by status" icon="document">
Use HTTP or gRPC status for login, permission, retry, and refresh decisions.
</Card>
<Card title="Use codes" icon="setting">
Read application codes from `google.rpc.ErrorInfo.metadata.errorCode`. Do not parse English text.
</Card>
<Card title="Keep request IDs" icon="magnifier">
Collect `requestId`, time, path, and status for support.
</Card>
<Card title="Protect secrets" icon="approve-check-circle">
Never log tokens, cookies, OAuth2 codes, Provider credentials, or passwords.
</Card>
</CardGrid>
## Continue Reading
- [Client Integration Guide](../../develop/client-integration/)
- [SDK and API Examples](../../develop/sdk-and-api-examples/)
- [Troubleshooting](../../operations/troubleshooting/)
- **Classify by status**: Use HTTP or gRPC status for login, permission, retry, and refresh decisions.
- **Use codes**: Read application codes from `google.rpc.ErrorInfo.metadata.errorCode`. Do not parse English text.
- **Keep request IDs**: Collect `requestId`, time, path, and status for support.
- **Protect secrets**: Never log tokens, cookies, OAuth2 codes, Provider credentials, or passwords.

@ -36,11 +36,3 @@ description: Short definitions for common SyncTV security, deployment, media, re
| publisher-node proxy | HLS model where non-publisher nodes read segments from the publishing node over gRPC | multi-replica livestreaming |
| fail-closed | Rejecting a business request when a critical dependency or event write fails, avoiding split database/cache state | write operations, realtime events, transactional outbox |
| fanout | Distributing one business change to local connections, nodes, or subscribers | WebSocket and cluster realtime events |
## Continue Reading
- [Architecture Overview](../../overview/architecture/)
- [Quick Start](../../install/quick-start/)
- [Configuration Index](../configuration-index/)
- [Client Integration Guide](../../develop/client-integration/)
- [Troubleshooting](../../operations/troubleshooting/)

@ -76,11 +76,3 @@ grpcurl -plaintext -d '{
## Relationship With OpenAPI
OpenAPI documents HTTP APIs only. gRPC debugging uses reflection or protobuf files. See [OpenAPI Access](../openapi/) for Swagger UI and OpenAPI JSON.
## Continue Reading
- [SDK and API Examples](../../develop/sdk-and-api-examples/)
- [Client Integration Guide](../../develop/client-integration/)
- [OpenAPI Access](../openapi/)
- [Errors](../errors/)
- [API and Protobuf Evolution](../api-versioning/)

@ -1,11 +1,9 @@
---
title: Limitations and Non-goals
description: Current SyncTV boundaries, design tradeoffs, and capabilities that should not be assumed.
title: Known Limitations
description: Current release limits for deployment, media, clustering, authentication, and API stability.
---
import { Card, CardGrid } from '@astrojs/starlight/components';
Current design boundaries are not long-term roadmap commitments.
These limits apply to the current release.
## Deployment Boundaries
@ -55,26 +53,9 @@ SyncTV is in a new-project phase. Its own protobuf, HTTP fields, and Realtime me
See [API and Protobuf Evolution](../api-versioning/).
## Non-goals
<CardGrid>
<Card title="Not media storage" icon="document">
SyncTV aggregates and proxies external media; it does not replace object storage or media libraries.
</Card>
<Card title="Not a CDN" icon="cloud-download">
Proxy and slice cache do not replace CDN capacity planning.
</Card>
<Card title="Not a universal transcoder" icon="puzzle">
Transcoding depends on the Provider or upstream media system.
</Card>
<Card title="Not a public management plane" icon="setting">
management gRPC and metrics need controlled access.
</Card>
</CardGrid>
## Continue Reading
## System Responsibilities
- [Architecture Overview](../../overview/architecture/)
- [Playback and Proxy Model](../../use/playback-and-proxy/)
- [Capacity Planning](../../operations/capacity-planning/)
- [Security Hardening and Rotation](../../operations/security-hardening-and-rotation/)
- **Media storage**: External object storage, network drives, or media libraries retain media; SyncTV aggregates and proxies it.
- **Content delivery**: A CDN handles large-scale distribution; proxy and slice cache optimize controlled forwarding and Range requests.
- **Transcoding**: The Provider or upstream media system supplies transcoding.
- **Management access**: management gRPC and metrics are accessed through a Unix socket, private network, VPN, or controlled cluster entry point.

@ -107,9 +107,3 @@ Disabled or unused features may not emit their metrics. Do not expose the metric
| `gop_cache_drops_total` | counter | none | GOP cache evictions |
| `gop_cache_memory_bytes` | gauge | none | GOP cache memory usage |
| `livestream_flv_slow_client_terminations_total` | counter | none | FLV slow-client terminations |
## Continue Reading
- [Metrics Monitoring](../../configuration/metrics/)
- [Observability Runbook](../../operations/observability/)
- [Capacity Planning](../../operations/capacity-planning/)

@ -94,11 +94,3 @@ docker build \
--build-arg SYNCTV_BUILD_FEATURES="k8s,mimalloc,tls-aws-lc,tls-webpki-roots,tls-native-roots" \
-t synctv:production-no-openapi .
```
## Continue Reading
- [SDK and API Examples](../../develop/sdk-and-api-examples/)
- [Client Integration Guide](../../develop/client-integration/)
- [gRPC Debugging](../grpc/)
- [Errors](../errors/)
- [API and Protobuf Evolution](../api-versioning/)

@ -3,7 +3,7 @@ title: Runtime Settings Reference
description: Hot-reload database settings, semantics, defaults, validation, scope, and CLI examples.
---
import { Aside, Card, CardGrid, TabItem, Tabs } from '@astrojs/starlight/components';
import { Aside, TabItem, Tabs } from '@astrojs/starlight/components';
## What Runtime Settings Are
@ -82,7 +82,7 @@ These settings are stored as JSON arrays of stable permission names, for example
["view_members", "view_chat_history", "use_voice_chat", "use_p2p_media"]
```
See [Rooms, Permissions, and Preferences](../../use/rooms-permissions/) for permission names, role defaults, and room override rules.
See [Roles, Permissions, and Preferences](../../admin/permissions/) for permission names, role defaults, and room override rules.
### Room
@ -142,7 +142,7 @@ All registration modes are disabled by default. Production deployments should en
A missing provider instance means that login entry point is unavailable. Missing or false `enableSignup` blocks first-time OAuth2 account creation while existing linked OAuth2 logins continue to work. `signupNeedReview=true` stores first-time OAuth2 signup in the user registration review queue; approval creates the local account and OAuth2 binding.
User-level 2FA and notification preferences are user preferences, not runtime settings. Provider instance bindings are stored on provider credentials created during provider login. See [Rooms, Permissions, and Preferences](../../use/rooms-permissions/).
User-level 2FA and notification preferences are user preferences. Provider instance bindings are stored on provider credentials created during provider login. See [Roles, Permissions, and Preferences](../../admin/permissions/).
### Proxy
@ -254,17 +254,7 @@ synctv settings update --set 'oauth2.providers=[{"name":"github","enableSignup":
## Before Changing Values
<CardGrid>
<Card title="Confirm Hot-Reload Scope" icon="setting">
Ports, secrets, database, Redis, TLS, and cache enablement are startup configuration, not runtime settings.
</Card>
<Card title="Read Current Value" icon="magnifier">
Run `synctv settings get <key>` before changing a value and keep it for rollback.
</Card>
<Card title="Watch Replicas" icon="cloud-download">
Multi-replica sync depends on PostgreSQL notifications; observe all replicas after changes.
</Card>
<Card title="Record Reason" icon="document">
Keep reasons for registration, room creation, proxy, and permission-default policy changes.
</Card>
</CardGrid>
- **Confirm Hot-Reload Scope**: Ports, secrets, database, Redis, TLS, and cache enablement are startup configuration, not runtime settings.
- **Read Current Value**: Run `synctv settings get <key>` before changing a value and keep it for rollback.
- **Watch Replicas**: Multi-replica sync depends on PostgreSQL notifications; observe all replicas after changes.
- **Record Reason**: Keep reasons for registration, room creation, proxy, and permission-default policy changes.

@ -1,49 +0,0 @@
---
title: Sign In and Account Security
description: How users sign in to SyncTV and safely use passwords, OPAQUE, passkeys, email, OAuth2, and 2FA.
---
import { Aside, Steps } from '@astrojs/starlight/components';
SyncTV can enable several sign-in methods. The methods shown in the UI depend on administrator configuration.
## Sign-In Methods
| Method | Requires | Good for |
| --- | --- | --- |
| OPAQUE password login | Local password | Public client local password login without storing direct password-verifier equivalents |
| Direct password login | Username or email and password | Restricted environments where an OPAQUE client is unavailable while the server still stores and verifies OPAQUE credentials |
| Passkey/WebAuthn | Browser, OS account, or security key | Passwordless sign-in or second factor |
| Email code | A reachable verified email address | Sign-in, verification, recovery, or MFA |
| OAuth2/OIDC | Third-party account | GitHub, Google, Logto, or generic OIDC |
## Before Enabling 2FA
Make sure you have at least two local verification methods: local password, passkey/WebAuthn, or verified email. OAuth2 does not count as a local 2FA factor.
<Aside type="caution">
Do not keep only one passkey and remove password or verified email. Device loss, browser profile damage, or passkey sync issues can block account recovery.
</Aside>
## When a Second Factor Is Required
<Steps>
1. Complete the first factor: OPAQUE password login, direct password login, passkey, email sign-in, or OAuth2.
2. If SyncTV asks for 2FA, choose one of the available second factors.
3. Complete email code or passkey/WebAuthn.
4. After signing in, confirm that at least two local verification methods remain available.
</Steps>
Public client local password login prefers OPAQUE. Direct password login serves restricted environments where the OPAQUE exchange is unavailable; the server immediately creates or verifies OPAQUE credentials from the submitted password.
## Account Issues
| Symptom | Check first |
| --- | --- |
| Password login fails | Username, password, account ban, 2FA requirement |
| Email code does not arrive | Address, spam folder, verified email, SMTP availability |
| OAuth2 callback does not sign in | Registration review, existing binding, callback URL |
| Passkey is unavailable | Browser, OS account, security key, current domain |
| 2FA blocks access | Whether two local verification methods still exist |
When reporting a problem, include time, username, sign-in method, error text, and `requestId`. Do not send passwords, tokens, cookies, OAuth2 codes, or verification codes.

@ -1,24 +0,0 @@
---
title: Chat
description: How users use room chat and identify mute, disabled chat, or Realtime problems.
---
Chat is a room realtime feature. Sending messages depends on room settings and the user's `send_chat_messages` permission.
## Common States
| Symptom | Possible cause | What to do |
| --- | --- | --- |
| Can read but not send | Chat disabled, muted, or missing `send_chat_messages` | Contact a room administrator |
| Others do not see a sent message | Realtime disconnected, rate limited, or room state issue | Re-enter the room and record the time |
| Only you miss new messages | Browser network, proxy, or WebSocket issue | Refresh or change network |
| Everyone misses messages | Server Realtime, Ingress, or cluster event issue | Ask an administrator to inspect runtime state |
## Good Practices
- To quiet the whole room, ask a room administrator to disable chat.
- To restrict one user, use member permissions instead of changing room defaults.
- Do not send passwords, tokens, cookies, Provider credentials, or OAuth2 codes in chat.
- When reporting problems, provide room ID, time, a summary of the message, and error text.
Protocol details are covered in [Realtime API](../../develop/realtime-api/).

@ -1,31 +0,0 @@
---
title: Use SyncTV
description: User documentation for signing in, joining rooms, synchronized playback, chatting, adding media, notifications, and troubleshooting.
---
import { LinkCard, CardGrid } from '@astrojs/starlight/components';
To start a synchronized playback session, begin with “Create and Join Rooms”. Account, playback, chat, media, notifications, and troubleshooting each have their own page.
<CardGrid>
<LinkCard title="Sign In and Account Security" href="./accounts-security/" description="Use password, OPAQUE, passkeys, email, OAuth2, and 2FA safely." />
<LinkCard title="Create and Join Rooms" href="./rooms/" description="Join public rooms, enter passwords, submit reviews, create rooms, and understand join failures." />
<LinkCard title="Synchronized Playback" href="./synchronized-playback/" description="Follow room playback state, use playback controls, handle seek, media changes, and drift." />
<LinkCard title="Chat" href="./chat/" description="Use room chat and understand mute, disabled chat, and Realtime issues." />
<LinkCard title="Add Media" href="./media-sources/" description="Add direct URLs, Alist, Emby/Jellyfin, Bilibili, remote Providers, and live entries." />
<LinkCard title="Notifications and Preferences" href="./preferences-notifications/" description="Manage notification preferences, default Provider, linked login methods, and security preferences." />
<LinkCard title="User Troubleshooting" href="./troubleshooting/" description="Diagnose account, room, playback, chat, media, and notification issues by symptom." />
</CardGrid>
## Core Objects
| Object | Where users see it | Common symptoms |
| --- | --- | --- |
| Account | Sign-in, personal settings, notifications, security checks | Login failure, unavailable 2FA, unverified email |
| Room | Room list, room entry points, playback page | Cannot join, password required, waiting for review |
| Playlist | Media queue inside a room | Media missing, cannot add, order changed |
| Current playback | Player and sync state | Out of sync, switch failed, URL expired |
| Chat | Room sidebar | Cannot send, messages not syncing, chat disabled |
| Provider | Media source and playback origin | Expired credentials, unsupported direct headers, slow proxy |
For the product model, see [Rooms](../concepts/rooms/), [Playback Model](../concepts/playback-model/), and [Permissions Model](../concepts/permissions/).

@ -1,137 +0,0 @@
---
title: Add Media
description: Add direct URLs, Alist, Emby/Jellyfin, Bilibili, RTMP livestreaming, and remote Provider media.
---
import { Aside, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
See the [Provider User Guide](../provider-guide/) for binding, preview, dynamic-playlist, and advanced playback capabilities across video platforms, media servers, and NAS systems.
## Choose a Source
Provider is the adapter layer that turns external media into SyncTV playback results. Before integrating, answer:
| Question | Why it matters |
| --- | --- |
| Can the client access the media directly? | Decides direct play versus proxy |
| Does the upstream require special headers or cookies? | Decides whether browsers can direct play |
| Are credentials user-owned or instance-owned? | Decides user binding, Provider instance, and encryption |
Built-in Providers cover video and live platforms, media servers, file services, NAS systems, direct URLs, and livestream sources. A remote Provider instance is stored in the database and connects SyncTV to a separate Provider service.
## Before Adding Media
<Steps>
1. Configure `security.credential_encryption_key` or `_file`.
2. Confirm local Provider timeouts: `media_providers.<type>.request_timeout_seconds` and `connect_timeout_seconds`.
3. Create a remote Provider instance through management APIs or CLI if needed.
4. Test login, browse, search, parse, and playback with an administrator.
5. Test direct playback, proxy playback, and Range seek.
6. Watch Provider error rate, proxy errors, slice cache hits, and upstream status.
</Steps>
<Aside type="caution">
Do not put Provider tokens, cookies, passwords, or API keys in client logs, URL queries, or media `sourceConfig`. Credentials should be resolved by the server-side Provider credential layer.
</Aside>
## Source Recipes
<Tabs syncKey="provider-recipes-en">
<TabItem label="Alist" icon="seti:folder">
**Use for**: mounted drives, directories, file browse, and search.
**Focus**:
- Login, list directories, search, choose a file, and add it to a playlist.
- Upstream URLs may require a specific `User-Agent`.
- If the browser cannot set required headers, use proxy playback.
- Large directories should use pagination, search, and caching.
**Validate**: listing works, search works, either direct or proxy playback works, and seek does not produce continuous 4xx/5xx.
</TabItem>
<TabItem label="Emby/Jellyfin" icon="puzzle">
**Use for**: existing media libraries, shows, subtitles, and transcoding.
**Focus**:
- Playback results may include multiple modes, subtitles, and metadata.
- Clients should use `default_mode` and `PlaybackClientProfile`.
- Unsupported codecs or containers should request transcoding or a compatible result.
- Server URL, account, and TLS policy must be managed explicitly.
**Validate**: library listing, playback URLs, subtitles, and direct/transcode modes work with client capabilities.
</TabItem>
<TabItem label="Bilibili" icon="youtube">
**Use for**: parsing Bilibili videos with QR or SMS credentials.
**Focus**:
- Sensitive to `Referer`, `User-Agent`, cookies, and Range.
- Direct and proxy headers must match Provider output.
- Expired credentials should ask the user to log in again.
- Upstream rate limits or CDN changes may look like temporary Provider failures.
**Validate**: parse succeeds, proxy requests include required headers, seek works, and credential expiry is understandable.
</TabItem>
<TabItem label="Direct URL" icon="external">
**Use for**: stable URLs, public object storage links, or internal media addresses.
**Focus**:
- Direct play only works when the client can access the URL.
- If the URL is server-network-only, use proxy.
- Prefer upstreams that support Range.
- Signed URLs require playback info refresh before expiry.
**Validate**: the client can GET/Range the URL, or SyncTV proxy can access it.
</TabItem>
<TabItem label="RTMP/Live" icon="youtube">
**Use for**: room livestream publishing and HLS/FLV playback.
**Focus**:
- RTMP is a publish entry, not a normal VOD Provider.
- The member needs `manage_live_streams` permission to manage live streams and create publish keys.
- Multi-replica deployments need a clear HLS backend: publisher-node proxy, `shared_file`, or OSS.
- Live paths depend more on ports, storage, and connection drain.
**Validate**: publish key creation, RTMP publish, HLS/FLV playback, and no random 404s in multi-replica mode.
</TabItem>
</Tabs>
## Local and Remote Providers
| Mode | Configuration | Use case |
| --- | --- | --- |
| Local built-in Provider | `media_providers` YAML timeouts | SyncTV directly accesses upstream Providers |
| Provider instance | Management API/CLI, stored in database | Multiple instances, credentials, or remote services |
| Remote Provider | Instance `endpoint`, `tls`, `jwt_secret`, etc. | Separate Provider capability or network boundary |
Configuration needed by the remote Provider to access upstream media belongs to that remote service, not the SyncTV `media_providers` object.
## Credentials and Security
- Use `security.credential_encryption_key_file`.
- Make credential ownership explicit: user, instance, or remote Provider service.
- Never write cookies, tokens, API keys, or passwords into `sourceConfig`, URL query, logs, or screenshots.
- Before rotation, confirm whether credentials are referenced by playlists, provider credentials, or remote instances.
See [Security Hardening and Rotation](../../operations/security-hardening-and-rotation/).
## Troubleshooting
| Symptom | Check first |
| --- | --- |
| Browse works but playback fails | Playback URL, headers, proxy mode, upstream Range |
| Direct works but proxy fails | Headers sent to proxy and whether upstream blocks server IP |
| Proxy works but direct fails | Browser header restrictions, CORS, client network |
| Bilibili intermittent 403 | Cookie, Referer, User-Agent, CDN behavior |
| Multi-replica live 404 | Publisher node, HLS backend, shared storage, OSS |
## Next Steps
- [Media Sources](../../concepts/media-providers/)
- [Playback Model](../../concepts/playback-model/)
- [Media Providers](../../configuration/media-providers/)
- [Proxy Slice Cache](../../configuration/proxy-slice-cache/)
- [Livestream Configuration](../../configuration/livestream/)

@ -1,32 +0,0 @@
---
title: Notifications and Preferences
description: Manage notification preferences, linked login methods, and security preferences.
---
Personal settings affect only the current user. Administrators configure platform capabilities such as SMTP, OAuth2 providers, Provider instances, and registration policy. User preferences decide how you use those capabilities.
## Common Settings
| Setting | Affects |
| --- | --- |
| Notification preferences | Room invitations, room events, system announcements, in-app and email delivery |
| Linked methods | Password, passkey/WebAuthn, email, OAuth2 bindings |
| 2FA | Whether local sign-in requires a second factor |
| Email status | Verification, recovery, and MFA email availability |
Provider instance bindings are stored on provider credentials created during provider login, not in user preferences.
## Missing Notifications
| Symptom | Check first |
| --- | --- |
| No email | Verified address, notification preference, spam folder |
| No in-app notification | Disabled category or already-read notification |
| One category missing | Whether that room or system event actually happened |
| Nobody receives email | Administrator should check SMTP configuration and delivery logs |
## Security Preferences
Before changing login methods, make sure you can complete the next sign-in. After enabling 2FA, do not remove local methods until only one remains. OAuth2 can be convenient, but it does not count as a local 2FA factor.
For account details, see [Sign In and Account Security](../accounts-security/).

@ -1,163 +0,0 @@
---
title: Provider User Guide
description: Bind accounts, preview resources, create dynamic playlists, and use video, media-server, and NAS Providers.
---
import { Aside, Steps } from '@astrojs/starlight/components';
SyncTV Providers convert external platforms, media servers, and NAS resources into playable media. The App consumes typed source configs, covers, thumbnails, subtitles, danmaku, quality modes, and proxy URLs returned by each Provider.
## Common Workflow
<Steps>
1. Open **Platform Bindings** in the App account center and select a Provider and Provider instance.
2. Sign in, scan a code, or provide the Cookie, token, or API key required by that Provider.
3. Open the room media library, choose Add Media, and select the Provider.
4. Enter a URL or resource ID, or use discovery features such as categories, search, favorites, history, or folder browsing.
5. Preview the source. Every result carries a typed media or playlist source config that can be submitted directly.
6. Add one media item, select part of the preview, or create a dynamic playlist.
7. During playback, choose an available quality, direct mode, or proxy mode from the Provider result.
</Steps>
A `Provider instance` identifies where resolution runs. The default instance runs inside the SyncTV server; administrators can also configure remote instances. Credentials, saved sources, and playback requests retain that instance binding.
`Use room owner credential` binds the source to the room owner's Provider credential. It is useful for personal favorites, history, followed lists, and private libraries. The personal mode uses the requesting user's credential.
## Capability Matrix
| Provider | Binding | Single media | Dynamic playlists and browsing | Playback features |
| --- | --- | --- | --- | --- |
| Bilibili | QR code or SMS | Videos, multi-part videos, PGC episodes, live rooms | Popular, recommendations, UP videos, favorites, collections, series, watch later, history, follows, PGC timeline/index, live home/follows/areas | DASH, qualities, subtitles, danmaku, covers, part thumbnails |
| Twitch | OAuth access token; Followed Live requires `user:read:follows` | Live, VOD, Clip | Channel Videos/Highlights/Uploads/Clips, followed live, category live, live search | HLS qualities, chapters, storyboard, chat, schedule |
| YouTube | Public access is anonymous; optional Visitor Data, PO Token, Cookie | Videos, Shorts, live | Playlists, channel Videos/Shorts/Live, search, trending, subscriptions, liked videos, watch later | Progressive/adaptive formats, subtitles, storyboard, covers |
| Douyin | Optional Cookie | Video, live | User posts | Bitrates, covers, live chat |
| TikTok | Optional Cookie | Video, live | User posts | Formats, subtitles, covers, slideshow audio |
| Huya | Public resolution | Live, video | URL and room entry | HLS/FLV, CDN, qualities, live chat |
| Douyu | Public resolution | Live | Room number, alias, or URL | HLS/FLV, CDN, qualities, codecs, live chat |
| AcFun | Public resolution | Video, bangumi, live | URL or resource ID | Qualities, tags, VOD/live danmaku, covers |
| CCTV | Public resolution | Known columns, programs, and embeds | URL or resource ID | HLS/MP4, chapters, metadata, covers |
| Emby/Jellyfin | Server, username, password or API key | Movies, episodes, videos | Continue Watching, Next Up, recent, favorite media/people, playlists, collections, genres | Direct stream, server transcode, subtitles, covers, progress reporting |
| Alist | Endpoint, username, password, optional OTP | Files | Folders and search | Thumbnails, subtitles, direct/transcode, Range |
| Cloudreve | Endpoint, email, password | Files | Folders and search with page/cursor negotiation | Signed playback URLs, covers/thumbnails, Range |
| FNOS | Main endpoint, username, password, optional 2FA; WebDAV/media discovery | Files and native media items | Files, media library, favorites, history | File previews, posters, native transcode, favorite/watched/progress state |
| QNAP QTS / QuTS hero | Endpoint, username, password | Files | File Station folders and search | Thumbnails, pre-transcoded heights, realtime transcode capability, Range |
| Synology DSM | Endpoint, username, password, optional OTP | File Station files and Video Station items | Files, movies, TV, episodes, home videos, recordings | Thumbnails, posters, tracks, subtitles, remux, progress |
| Nextcloud | Endpoint plus app password, or Login Flow | Files | Folders, favorites, search | Preview API, BlurHash, dimensions/duration, Range |
| Seafile | Endpoint, username, password; encrypted-library unlock | Files | Library folders, starred, search | Thumbnails, download links, encrypted libraries, Range |
| TrueNAS | Endpoint and API key | Files | Folders and search under `/mnt` | File metadata, ACL/ZFS attributes, Range |
| Direct URL | None | HTTP(S) files, HLS, and related sources | Fixed source | Custom headers, Range, HLS segment proxy |
| RTMP / Live Proxy | Room permission or admin configuration | Push and external RTMP/HTTP-FLV | Live source | SyncTV HLS/FLV and lifecycle management |
## Video Platforms
### Bilibili
Bindings unlock favorites, watch later, history, followed live rooms, and followed PGC. Public videos, PGC, and live rooms can also be resolved anonymously.
The App offers two workflows:
- **URL parsing** accepts video, PGC season/episode, live room, UP space, favorite folder, collection, series, and live-area URLs. The backend returns typed candidates. Multi-part videos support selected-part addition and complete dynamic playlists.
- **Discovery** exposes popular, recommended, UP videos, favorite folders, history, followed PGC, live home, followed live, live areas, PGC timeline, and PGC index.
The PGC timeline supports anime, cinema, and guochuang across a zero-to-seven-day window in each direction. Preview keeps published, upcoming, and delayed entries; published entries carry their real episode ID and CID. The PGC index supports category, order, direction, completion status, area, year, and style filters. Selecting a season opens its full episode preview.
Dynamic playlists preserve upstream pagination. History uses Bilibili's native cursor, while popular, UP, favorites, seasons, and indexes use their own page or cursor contracts. Sequential, repeat-one, repeat-all, and shuffle playback advance with typed targets.
### Twitch
Bind an OAuth access token. SyncTV stores the Twitch user ID, client ID, and scopes. Followed Live requires `user:read:follows`; the App checks capabilities for the selected instance.
Media URLs support live channels, VODs, and Clips. Channel playlists support Videos, Highlights, Uploads, and Clips. Discovery includes Followed Live, Top Categories, Category Live, live-channel search, and Broadcaster Schedule.
### YouTube
Public videos work anonymously. Visitor Data and PO Token improve requests that need browser context. Subscriptions, Liked Videos, and Watch Later require a Cookie. Cookie material stays in server-side credential storage and upstream requests.
Video inputs accept IDs and `watch`, `youtu.be`, `shorts`, or `live` URLs. Playlists accept URLs or IDs. Channels accept `UC...` IDs and `/channel/UC...` URLs, with separate Videos, Shorts, and Live dynamic playlists.
Preview lists support selected-item addition and whole-source dynamic playlist creation. Personal feeds are enabled according to the selected Provider instance's Cookie capability. Shared mode uses the room owner's binding.
### Douyin and TikTok
Each Provider has independent resource and API models. Video and live URLs return platform metadata and playback variants. User profiles resolve to stable user identifiers for user-post dynamic playlists. Cookie bindings provide login, region, and risk-control context where required.
### Huya, Douyu, AcFun, and CCTV
- Huya resolves live rooms and videos with qualities, CDN choices, HLS/FLV, and chat capability.
- Douyu accepts numeric room IDs, aliases, and URLs, and exposes codecs, qualities, and CDN choices.
- AcFun supports videos, bangumi, and live, with distinct VOD and live danmaku protocols.
- CCTV resolves known column, program, and embed pages and returns native streams, chapters, and metadata.
## Media Servers and File Services
### Emby and Jellyfin
Both use the `emby` Provider. Bind the server root URL, target username, and password, or use an API key. The upstream user's permissions control library visibility, transcoding, and subtitles.
Dynamic sources include Continue Watching, Next Up, Recently Added, Favorite Media, Favorite People, Person Items, server playlists, collections, genres, and genre items. Folder preview entries carry typed playlist source configs for continued browsing.
Playback start, progress, pause, and stop events are reported upstream. SyncTV requests playback information for the current client profile and exposes available direct and transcode modes. Negotiated playback sessions are scoped to a room. Stop, lease reaping, and server shutdown terminate the room's active encodings.
### Alist and Cloudreve
Alist supports folder browsing, search, thumbnails, subtitles, direct streams, and upstream transcodes. Directory passwords live in source configs; account passwords live in encrypted credentials.
Cloudreve supports browsing, search, signed playback URLs, and thumbnails. Page-based servers use page requests. Cursor-based servers use opaque cursors for dynamic playlists. The response pagination oneof is the authoritative mode.
## NAS and Private Cloud
### FNOS
FNOS login supports a main endpoint, optional WebDAV/media endpoints, 2FA, and trusted-device state. Discovery reports whether the native media service is available.
The App provides separate **Files** and **Media Library** workflows. Files use file thumbnails and download/Range. Media Library uses posters, metadata, favorites, history, watched state, progress, and native transcode. Saved sources use distinct `File` and `LibraryItem` variants. Native transcode sessions receive `media.quit` on profile replacement, playback stop, lease reaping, and server shutdown. The background reaper retries transient cleanup failures.
### QNAP
QNAP uses File Station for browsing and search. Capability discovery reports the device's realtime transcode, hardware transcode, QTranscode, Multimedia Codec, and HD Station flags for binding diagnostics. Playback exposes original files and completed pre-transcoded files. File items advertise the available pre-transcoded heights.
### Synology
Synology login supports OTP. File Station handles normal files; Video Station handles movies, shows, episodes, home videos, and recordings. Video items carry posters, tracks, subtitles, and playable file identity, and playback progress is reported to DSM. SyncTV tracks every Video Station `stream_id` and calls DSM `close` on playback stop, lease reaping, and server shutdown.
### Nextcloud
Use an app password or the official Login Flow. Entries preserve file ID, ETag, MIME type, owner, favorite state, Preview capability, BlurHash, dimensions, and duration. Covers use the Nextcloud Preview API through signed SyncTV routes.
### Seafile
Select a library after login. Encrypted libraries prompt for a separate unlock password. Dynamic sources support folders, starred items, and repository search; files retain object ID and thumbnail capability.
### TrueNAS
Bind with an API key. Browsing is scoped to storage mounts under `/mnt`. Folder and search results preserve real path, mount ID, permissions, ACLs, extended attributes, and ZFS attributes.
## Page and Cursor Pagination
Dynamic responses use an explicit pagination oneof:
- `page` serves upstreams with random page access.
- `cursor` serves native continuations such as Cloudreve, Bilibili history, Twitch, and YouTube.
The App sends the next page number for page responses and returns `next_cursor` for cursor responses. Cursors are opaque values that clients store and return unchanged.
Sequential autoplay continues scanning pages until it finds the current target and next playable item. Shuffle uses a bounded sample to keep large folders under control.
## Credentials and Security
<Aside type="caution" title="Production requirement">
Configure a stable `security.credential_encryption_key_file` and serve SyncTV over TLS. Submit Cookies, passwords, tokens, and API keys only to a trusted SyncTV deployment.
</Aside>
Credentials are scoped by user, Provider, server ID, and Provider instance. The same upstream host can be bound independently through several instances. Migrate media and dynamic playlists that reference a binding before deleting it.
## Troubleshooting Order
1. Confirm that the selected Provider instance matches the binding.
2. Refresh account state and scopes/capabilities in Platform Bindings.
3. Preview again and identify whether the failure happens during listing, parsing, playback generation, or proxy transport.
4. Inspect server ID, resource ID, pagination mode, and credential-sharing choice in the source config.
5. Select a `proxy_*` mode for header-bound, DASH, or HLS sources that need server transport.
6. Continue with [Provider Configuration](../../configuration/media-providers/), [Playback and Proxy](../playback-and-proxy/), and [User Troubleshooting](../troubleshooting/).

@ -1,61 +0,0 @@
---
title: Create and Join Rooms
description: How users join public rooms, enter passwords, submit reviews, create rooms, and understand room roles.
---
import { Aside, Steps, TabItem, Tabs } from '@astrojs/starlight/components';
A room is where a group watches and chats together. Whether you can enter depends on visibility, password, review, guest access, member limit, and ban state.
## Join a Room
<Tabs syncKey="join-room-user-en">
<TabItem label="Open room" icon="rocket">
<Steps>
1. Open the room from the room list or an existing room entry point.
2. If no password or review is required, join directly.
3. After joining, your role decides which chat, playlist, and playback controls are available.
</Steps>
</TabItem>
<TabItem label="Password" icon="seti:lock">
<Steps>
1. Enter the room password.
2. If review is also required, wait for a room administrator.
3. Avoid repeated failed submissions because they may trigger rate limits or audit logs.
</Steps>
</TabItem>
<TabItem label="Review" icon="approve-check-circle">
<Steps>
1. Submit a join request.
2. Wait for a room administrator or creator.
3. If rejected, confirm room rules before trying again.
</Steps>
</TabItem>
</Tabs>
<Aside type="note">
Different buttons for creators, room admins, members, and guests are usually permission behavior, not a UI error.
</Aside>
## Create a Room
If ordinary users can create rooms:
1. Use a clear name and description.
2. Decide whether the room needs a password.
3. Enable join review for semi-public rooms.
4. Set a member limit that fits the service and upstream media source.
5. Check default permissions for guests and members.
6. Join once with a normal member account.
## Cannot Join
| Symptom | Possible cause | What to do |
| --- | --- | --- |
| Password rejected | Password changed or mistyped | Ask the room administrator |
| Waiting for review | Join review is enabled | Wait or contact a room administrator |
| Permission denied | Not signed in, guest access disabled, or room ban | Sign in or contact a room administrator |
| Room is full | `maxMembers` reached | Wait or ask for a higher limit |
| Room missing | Hidden, deleted, or banned | Confirm the room entry point or contact an administrator |
For room and role boundaries, see [Rooms](../../concepts/rooms/) and [Permissions Model](../../concepts/permissions/).

@ -1,34 +0,0 @@
---
title: Synchronized Playback
description: How users follow room playback, use playback controls, handle seek, switch media, and diagnose drift.
---
The SyncTV server owns room playback state. A client fetches the current state and playback info, then receives changes through Realtime.
## What Happens in a Room
| Behavior | Meaning |
| --- | --- |
| Play or pause | A permitted user changes state for room members |
| Seek | The room jumps to a new playback time |
| Switch media | Clients fetch a new playback info |
| Change speed | A permitted user changes shared playback speed |
| Reconnect | The client should refresh key state after network loss |
Users without playback permissions follow the room state. If controls are missing, check the room role and member permissions.
## Playback Failure
| Symptom | Try first | If it continues, collect |
| --- | --- | --- |
| Playback drift | Refresh or re-enter the room | Room ID, time, whether only you are affected |
| Media switch fails | Retry or refresh playlist | Media ID, error text, HTTP status |
| Playback URL expired | Fetch fresh playback info or re-enter | Provider name, expiry message, requestId |
| Seek hangs | Wait for buffering, check Range/proxy | Upstream status and proxy mode |
| Multiple users fail | Ask an admin to inspect WebSocket, Ingress, or Provider | Time range, room ID, affected users |
## Direct or Proxy
Browsers cannot set some upstream headers. If a Provider requires headers the client cannot set, use SyncTV proxy playback. Proxy playback uses SyncTV egress bandwidth but can normalize headers and hide upstream credentials.
For the full model, see [Playback Model](../../concepts/playback-model/). Client implementers should read [Client Integration Guide](../../develop/client-integration/).

@ -1,31 +0,0 @@
---
title: User Troubleshooting
description: Diagnose sign-in, room, playback, chat, media, and notification issues by symptom.
---
Start with the symptom, then decide whether to contact a room administrator or platform administrator. Do not send passwords, tokens, cookies, Provider credentials, OAuth2 codes, or verification codes.
## Quick Diagnosis
| Problem | Check first | Owner |
| --- | --- | --- |
| Sign-in fails | Username, password, email verification, 2FA, account ban | Platform administrator |
| OAuth2 did not sign in | Registration review, third-party account binding | Platform administrator |
| Cannot join room | Password, review state, room ban, member limit | Room administrator |
| Cannot control playback | `control_playback_state`, `navigate_playback` | Room administrator |
| Cannot play media | Provider credentials, direct headers, proxy path, upstream Range | Room or platform administrator |
| WebSocket keeps disconnecting | Network, browser proxy, reverse proxy timeout, connection limits | Platform administrator |
| Cannot chat | `send_chat_messages`, room chat switch, mute state | Room administrator |
| No notifications | Preferences, verified email, SMTP availability | Platform administrator |
## Include in Reports
| Information | Example |
| --- | --- |
| Time | 2026-05-10 21:30 Asia/Shanghai |
| Room or media | Room ID, media name, media ID |
| Action | Sign in, join room, click play, send message, add media |
| Error | UI message, HTTP status, `requestId` |
| Scope | Only you, or several members at the same time |
For playback issues, also include direct/proxy mode, whether you were seeking, and whether it started after a media switch. Operators use [Troubleshooting](../../operations/troubleshooting/) for production diagnosis.

@ -1,108 +1,57 @@
---
title: SyncTV 文档
description: SyncTV 的使用、管理、安装、配置、运维和客户端集成文档。
template: splash
hero:
tagline: 自托管同步观影应用,用房间组织播放、聊天、媒体源和成员协作。
actions:
- text: 开始使用
link: use/
icon: rocket
variant: primary
- text: 安装部署
link: install/choose-path/
icon: approve-check-circle
- text: 开发集成
link: develop/client-integration/
icon: document
title: SyncTV Server
description: 部署、配置和运营 SyncTV Server。
tableOfContents: false
---
import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
import LocaleRedirect from '../../components/LocaleRedirect.astro';
import LocaleChoiceTracker from '../../components/LocaleChoiceTracker.astro';
<LocaleRedirect />
<LocaleChoiceTracker />
<img src="/screenshots/room-macos.png" alt="SyncTV 房间同步播放" />
SyncTV 的日常入口是房间。用户在房间里同步观看视频、聊天、切换播放列表;房间管理员控制成员和权限;平台管理员维护账号、审核、Provider、直播和运行策略。
这份文档按真实任务组织。第一次使用先进入“使用 SyncTV”,接管实例先进入“管理 SyncTV”,上线部署先进入“安装与升级”,客户端接入先进入“开发与集成”。
原生客户端可从 [SyncTV App Releases](https://github.com/synctv-org/synctv-app/releases/latest) 下载。
## 选择入口
<CardGrid>
<LinkCard
title="使用 SyncTV"
href="use/"
description="登录、加入房间、同步观看、聊天、添加媒体和管理个人设置。"
/>
<LinkCard
title="管理实例"
href="admin/"
description="管理用户、房间、审核、Provider、直播、运行时设置和维护任务。"
/>
<LinkCard
title="安装或升级"
href="install/choose-path/"
description="选择 Compose、源码运行或 Helm/Kubernetes 路径,并完成生产上线检查。"
/>
<LinkCard
title="开发客户端"
href="develop/client-integration/"
description="使用 OpenAPI、gRPC、WebSocket Realtime、ticket、播放信息和错误码。"
/>
</CardGrid>
## 常用任务
| 目标 | 页面 |
| --- | --- |
| 登录并保护账号 | [登录与账号安全](use/accounts-security/) |
| 创建或加入房间 | [创建和加入房间](use/rooms/) |
| 处理播放不同步或失败 | [同步观看](use/synchronized-playback/) 和 [用户排障](use/troubleshooting/) |
| 添加媒体源 | [添加媒体](use/media-sources/) |
| 管理用户、房间和审核 | [管理 SyncTV](admin/) |
| 启动自托管实例 | [快速开始](install/quick-start/) |
| 接入客户端 | [客户端集成指南](develop/client-integration/) |
| 参与讨论或查看贡献者 | [讨论与贡献者](overview/community/) |
## 理解 SyncTV
<CardGrid>
<Card title="房间" icon="puzzle">
成员、播放列表、聊天、权限和当前播放状态都围绕房间组织。见 [房间概念](concepts/rooms/)。
</Card>
<Card title="同步观看" icon="youtube">
服务端保存房间播放状态,客户端通过 Realtime 跟随播放、暂停、seek 和媒体切换。见 [播放模型](concepts/playback-model/)。
</Card>
<Card title="媒体源" icon="cloud-download">
Provider 把 Alist、Emby/Jellyfin、Bilibili、直链、远程服务或直播入口变成可播放结果。见 [媒体源概念](concepts/media-providers/)。
</Card>
<Card title="权限" icon="seti:lock">
全局角色、房间角色、成员覆盖和房间设置共同决定用户能做什么。见 [权限模型](concepts/permissions/)。
</Card>
</CardGrid>
## 上线前再看
<CardGrid>
<Card title="生产部署清单" icon="approve-check-circle">
上线前确认 TLS、secret、PostgreSQL、Redis、备份、metrics、管理面和恢复流程。
</Card>
<Card title="运行边界" icon="setting">
了解 PostgreSQL、Redis、secret、管理面、媒体代理和非目标,避免用错系统边界。
</Card>
<Card title="配置入口" icon="document">
配置文件、环境变量、runtime settings 和 CLI 覆盖的优先级不同,修改前先确认来源。
</Card>
</CardGrid>
从本地试用到生产上线见 [部署路径选择](install/choose-path/);运行依赖和非目标见 [运行边界](concepts/runtime-boundaries/);完整字段见 [配置总索引](reference/configuration-index/)。
## 许可证
SyncTV 使用 MIT 许可证。完整条款见仓库根目录的 `LICENSE` 文件。
<p class="docs-home-lead">
在单台服务器上使用 Docker Compose;在现有 Kubernetes 集群中使用 Helm。安装完成后配置公网入口、长期密钥、备份和监控。
</p>
<div class="docs-directory">
<section>
<h2>部署</h2>
<ul class="docs-link-list">
<li><a href="install/quick-start/"><strong>Docker Compose 安装</strong><span>服务器、NAS 或虚拟机</span></a></li>
<li><a href="install/helm/"><strong>Helm 安装</strong><span>Kubernetes、Ingress 与多副本</span></a></li>
<li><a href="operations/upgrades/"><strong>升级现有实例</strong><span>备份、迁移与回滚</span></a></li>
<li><a href="install/production-checklist/"><strong>生产部署清单</strong><span>TLS、密钥、数据与监控</span></a></li>
</ul>
</section>
<section>
<h2>配置</h2>
<ul class="docs-link-list">
<li><a href="configuration/how-configuration-works/"><strong>加载顺序</strong><span>YAML、环境变量与 secret 文件</span></a></li>
<li><a href="configuration/full-example/"><strong>配置示例</strong><span>最小生产配置和完整字段模板</span></a></li>
<li><a href="configuration/security/"><strong>安全与密钥</strong><span>JWT、OPAQUE、CORS 与凭据加密</span></a></li>
<li><a href="reference/configuration-index/"><strong>配置字段</strong><span>类型、默认值与重启要求</span></a></li>
</ul>
</section>
<section>
<h2>管理与运维</h2>
<ul class="docs-link-list">
<li><a href="admin/"><strong>管理 SyncTV</strong><span>用户、房间、权限与 Provider</span></a></li>
<li><a href="operations/observability/"><strong>监控与运行手册</strong><span>健康检查、metrics、日志与告警</span></a></li>
<li><a href="operations/backup-restore/"><strong>备份与恢复</strong><span>PostgreSQL、密钥与恢复演练</span></a></li>
<li><a href="operations/troubleshooting/"><strong>排障</strong><span>按错误、状态码和运行信号定位问题</span></a></li>
</ul>
</section>
<section>
<h2>开发与参考</h2>
<ul class="docs-link-list">
<li><a href="develop/local-development/"><strong>本地开发</strong><span>依赖、数据库、测试与代码生成</span></a></li>
<li><a href="reference/cli/"><strong>CLI</strong><span>服务控制与管理命令</span></a></li>
<li><a href="reference/openapi/"><strong>OpenAPI</strong><span>HTTP API 规范与客户端生成</span></a></li>
<li><a href="reference/grpc/"><strong>gRPC</strong><span>公开 API、management API 与 reflection</span></a></li>
</ul>
</section>
</div>

@ -1,75 +1,32 @@
---
title: 部署路径选择
description: 在单机生产 Compose、本地试用、源码运行和 Helm/Kubernetes 之间选择正确路径。
title: 选择部署方式
description: 比较 Docker Compose 与 Helm 的基础设施要求和运维成本。
---
import { Aside, Steps } from '@astrojs/starlight/components';
import Diagram from '../../../components/Diagram.astro';
import deploymentPathDark from '../../../assets/diagrams/deployment-path-zh-dark.svg';
import deploymentPathLight from '../../../assets/diagrams/deployment-path-zh-light.svg';
Docker Compose 覆盖大多数自托管环境。Helm 面向已经运行 Kubernetes、Ingress 和集中式 Secret 管理的平台。
## 路径
<table class="deployment-matrix">
<thead><tr><th>条件</th><th>Docker Compose</th><th>Helm</th></tr></thead>
<tbody>
<tr><td>运行环境</td><td>一台 Linux 服务器、NAS 或虚拟机</td><td>现有 Kubernetes 集群</td></tr>
<tr><td>SyncTV 副本</td><td>单副本</td><td>单副本或多副本</td></tr>
<tr><td>PostgreSQL / Redis</td><td>Compose 同时启动</td><td>使用集群内或托管服务</td></tr>
<tr><td>TLS 入口</td><td>现有反向代理</td><td>Ingress Controller</td></tr>
<tr><td>Secret</td><td>本地 env 文件</td><td>Kubernetes Secret 或外部 Secret 系统</td></tr>
<tr><td>开始安装</td><td><a href="../quick-start/">Docker Compose 安装</a></td><td><a href="../helm/">Helm 安装</a></td></tr>
</tbody>
</table>
长期运行的单机实例使用 **单机生产 Compose**。只有改代码、临时本地试用,或已经有 Kubernetes 平台时才切换路径。
源码开发使用[本地开发环境](../../develop/local-development/),其中的 Compose 文件只启动开发依赖。
<Diagram
light={deploymentPathLight}
dark={deploymentPathDark}
alt="SyncTV 部署路径选择图,按照是否长期运行、是否改代码、是否需要 Kubernetes 多副本选择单机生产 Compose、本地试用、源码运行或 Helm。"
caption="先判断运行目标,再进入对应部署文档。"
/>
## 生产要求
## 选择表
上线前完成以下项目:
| 路径 | 适合谁 | 启动方式 | 生产可用性 | 下一页 |
| --- | --- | --- | --- | --- |
| 单机生产 Compose | 自托管用户、小团队、一台服务器 | 预构建镜像 + `.env.postgres` + `.env.redis` + `.env.synctv` | 默认生产路径 | [快速开始](../../install/quick-start/) |
| 本地试用 | 临时看界面或功能 | `docker-compose.dev.yml` | 不可用于公网或长期运行 | [开发环境](../../develop/local-development/) |
| 源码运行 | 开发者、调试 API、改代码 | 容器依赖 + 本机 `cargo +nightly run` | 不作为部署方式 | [开发指南](../../develop/local-development/) |
| Helm/Kubernetes | 多副本、平台团队、统一 Ingress/监控 | Helm values + Kubernetes Secret/PVC/Ingress | 可用于生产,但复杂度更高 | [Helm 部署](../helm/) |
- 持久化并备份 PostgreSQL。
- 长期保存 JWT、OPAQUE 和凭据加密 secret。
- 公网入口启用 HTTPS。
- 多副本共享 PostgreSQL、Redis 和集群 secret。
- 升级前备份并验证数据库 migration。
## 单机生产 Compose
满足任一条件时使用:
- 只有一台服务器或一台 NAS/VM。
- 想尽快得到一个长期可用的 SyncTV 实例。
- 不想先理解 Kubernetes、Ingress controller、PVC、Secret operator。
- 可以自己管理 PostgreSQL 备份和几个长期 secret。
成功标准:
- `.env.postgres`、`.env.redis` 和 `.env.synctv` 已持久保存并备份。
- `make compose-config` 通过。
- `/health/ready` 返回 200。
- root 用户可以登录。
- PostgreSQL 有备份方案。
执行路径:
1. [快速开始](../../install/quick-start/):下载 Compose 文件、生成 env、设置 root 密码、启动服务。
2. [Docker Compose 部署](../docker-compose/):确认生产 Compose、开发 Compose、数据卷和端口边界。
3. [生产部署清单](../production-checklist/):上线前检查 TLS、secret、备份、metrics、告警和升级策略。
## 例外路径
| 场景 | 使用路径 | 边界 |
| --- | --- | --- |
| 只想临时体验 | 本地试用 | 使用生成的本地 env 文件,启动快;不要暴露公网或长期运行。 |
| 要改代码 | 源码运行 | PostgreSQL 和 Redis 可由开发 Compose 提供,SyncTV 本体由本机 Rust 工具链启动。 |
| 已有 Kubernetes 平台 | Helm | 先确定 HTTP/gRPC Ingress、Secret、PVC、metrics、Redis、HLS 存储和滚动更新策略。 |
| 需要多副本实时协作 | Helm 或自管多副本 | 所有副本必须共享 PostgreSQL、Redis、`redis.key_prefix` 和 `cluster.secret`。 |
## 决策底线
<Steps>
1. 只要对外提供服务,就不要使用开发 Compose。
2. 只要长期运行,就必须备份 PostgreSQL 和生产 secret。
3. 只要多副本运行,就必须共享 PostgreSQL、Redis、`redis.key_prefix` 和 `cluster.secret`。
4. 只要启用 HLS 多副本,就必须选择 publisher-node proxy、`shared_file` 或 OSS 之一。
5. 只要管理控制面使用 TCP,就必须配置 token,并避免暴露给普通公网入口。
</Steps>
<Aside type="tip">
如果还不确定,选单机生产 Compose。它是最小的生产闭环,后续仍可以迁移到 Helm 或其他编排系统。
</Aside>
完整检查项见[生产部署清单](../production-checklist/)。已有实例按[升级与迁移](../../operations/upgrades/)操作。

@ -98,11 +98,3 @@ kubectl -n synctv get pods
| 测试环境 | 目标版本已在测试环境完成启动、migration、登录、房间读写和 Provider 访问。 |
| 滚动更新 | `server.shutdown_drain_timeout_seconds` 小于 Kubernetes termination grace period。 |
| 回滚 | 已确认回滚版本、数据库状态和配置文件来源。 |
## 继续阅读
- [备份与恢复](../../operations/backup-restore/)
- [观测与运行手册](../../operations/observability/)
- [容量规划](../../operations/capacity-planning/)
- [安全加固与密钥轮换](../../operations/security-hardening-and-rotation/)
- [升级与迁移](../../operations/upgrades/)

@ -1,6 +1,6 @@
---
title: 快速开始
description: 用 Docker Compose 启动单机 SyncTV,并验证服务可用。
title: 使用 Docker Compose 安装
description: 在一台主机上启动 SyncTV、PostgreSQL 和 Redis,并验证服务状态。
---
import { Aside, Code, Steps } from '@astrojs/starlight/components';
@ -9,16 +9,16 @@ import {
githubCloneUrl,
} from '../../../lib/project';
单机生产部署包含一个 SyncTV 进程、一个 PostgreSQL 和一个 Redis。Kubernetes 或多副本部署先完成单机闭环,再进入 [Helm 部署](../../install/helm/) 和 [集群配置](../../configuration/cluster/)。
此安装在一台主机上运行 SyncTV、PostgreSQL 和 Redis。Kubernetes 环境直接使用 [Helm 安装](../../install/helm/)。
## 前置条件
- Docker 和 Docker Compose 可用。
- GNU Make 和 `openssl` 可用于生成环境文件。
- 当前目录可以长期保存 Compose 文件、`.env.postgres`、`.env.redis`、`.env.synctv` 和数据卷。
- 已准备 root 用户密码。生产环境使用密码管理器生成。
- 为 SyncTV 准备一个长期保留的工作目录。该目录保存 Compose 文件、三个 env 文件和数据卷。
- 使用密码管理器生成初始 root 密码。
## 启动
## 安装
<Steps>
1. 获取生产 Compose 配置:
@ -34,19 +34,19 @@ import {
make compose-init
```
3. 编辑 `.env.synctv`,至少设置 root 密码:
3. 编辑 `.env.synctv`,设置初始 root 密码:
```dotenv
SYNCTV_BOOTSTRAP_ROOT_PASSWORD=replace-with-a-strong-password
```
4. 检查 Compose 渲染结果:
4. 验证 Compose 配置:
```bash
make compose-config
```
5. 启动服务:
5. 在后台启动服务:
```bash
make compose-up
@ -55,20 +55,24 @@ import {
## 验证
查看容器状态并请求 readiness endpoint:
```bash
make compose-ps
curl -fsS http://localhost:8080/health/ready
```
成功后打开:
readiness 请求成功后,在浏览器打开:
```text
http://localhost:8080
```
默认 root 用户名是 `root`。密码来自 `.env.synctv` 中的 `SYNCTV_BOOTSTRAP_ROOT_PASSWORD`。
使用用户名 `root` 和 `.env.synctv` 中的 `SYNCTV_BOOTSTRAP_ROOT_PASSWORD` 登录。
## 备份数据与密钥
## 必须保存的值
备份 PostgreSQL,并将以下值保存在密码管理器或 Secret 管理系统中:
| 环境变量 | 用途 |
| --- | --- |
@ -78,7 +82,7 @@ http://localhost:8080
| `SYNCTV_BOOTSTRAP_ROOT_PASSWORD` | 首次创建 root 用户 |
<Aside type="caution">
不要删除或重新生成 `.env.synctv` 中的长期 secret。`SYNCTV_SECURITY_OPAQUE_SERVER_SETUP_SECRET` 和 `SYNCTV_SECURITY_CREDENTIAL_ENCRYPTION_KEY` 变化后,已有密码记录或 Provider 凭据可能不可用。
长期保留 `.env.synctv` 中的 secret。OPAQUE secret 关联现有密码记录,凭据加密密钥关联现有 Provider 凭据。
</Aside>
## 常见失败
@ -90,8 +94,8 @@ http://localhost:8080
| 浏览器跨域错误 | 在 `.env.synctv` 中设置 `SYNCTV_SERVER_CORS_ALLOWED_ORIGINS`,只填写 origin。 |
| root 用户无法登录 | 确认数据库首次启动时已设置 `SYNCTV_BOOTSTRAP_ROOT_PASSWORD`,并查看启动日志中的 bootstrap 结果。 |
## 继续阅读
## 上线前
- 按 [生产部署清单](../../install/production-checklist/) 补齐 TLS、备份、metrics 和告警。
- 需要解释 Compose 文件、端口和数据卷时,读 <a href={composeDeploymentDocsUrl}>Docker Compose 部署</a>。
- 本地源码开发见 [开发指南](../../develop/local-development/)。
- 按[生产部署清单](../../install/production-checklist/)配置 TLS、备份、metrics 和告警。
- <a href={composeDeploymentDocsUrl}>Docker Compose 参考</a>列出端口、数据卷和维护命令。
- [升级与迁移](../../operations/upgrades/)说明发布升级流程。

@ -148,10 +148,3 @@ Redis 丢失通常不破坏持久业务数据,但会造成短期行为变化
- 集群节点需要重新注册和 catch-up。
如果你依赖强 token 吊销语义,Redis 应使用高可用部署,并把 token 有效期设置得足够短。
## 继续阅读
- [安全加固与密钥轮换](../security-hardening-and-rotation/)
- [升级与迁移](../upgrades/)
- [生产部署清单](../../install/production-checklist/)
- [排障入口](../troubleshooting/)

@ -120,10 +120,3 @@ proxy egress bandwidth = concurrent_proxy_viewers * average_bitrate * peak_facto
在有 WebSocket 和直播连接时发布,确认 readiness 及时摘流,drain 时间足够。
</TabItem>
</Tabs>
## 继续阅读
- [观测与运行手册](../observability/)
- [配置:限流与连接限制](../../configuration/rate-limits/)
- [播放与代理模型](../../use/playback-and-proxy/)
- [集群配置](../../configuration/cluster/)

@ -120,12 +120,3 @@ security:
- `/metrics` 不应暴露公网。
- metrics token 或 Basic 密码必须通过 secret 注入。
- 指标适合容量、错误率、连接数和延迟观测,不应携带用户内容。
## 继续阅读
- [备份与恢复](../backup-restore/)
- [升级与迁移](../upgrades/)
- [观测与运行手册](../observability/)
- [认证与安全模型](../../admin/authentication-security/)
- [房间、权限与用户偏好](../../use/rooms-permissions/)
- [Runtime settings 参考](../../reference/runtime-settings/)

@ -1,6 +1,6 @@
---
title: 运行边界
description: PostgreSQL、Redis、secret、管理面、metrics、媒体代理和 SyncTV 非目标。
title: 部署与运行边界
description: PostgreSQL、Redis、secret、管理面、metrics、媒体代理和生产部署边界。
---
SyncTV 是应用服务,不是数据库、对象存储、媒体库、CDN 或公网管理平台。生产部署前先确认下面这些边界,能减少错误配置和错误预期。

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save