chore: update config template (#15344)

This commit is contained in:
DarkSky
2026-07-26 16:29:16 +08:00
committed by GitHub
parent 0d889bc643
commit b975e6b562
12 changed files with 54 additions and 211 deletions
-23
View File
@@ -1,23 +0,0 @@
# select a revision to deploy, available values: stable, beta, canary
AFFINE_REVISION=stable
# set the port for the server container it will expose the server on
PORT=3010
# set the host for the server for outgoing links
# AFFINE_SERVER_HTTPS=true
# AFFINE_SERVER_HOST=affine.yourdomain.com
# or
# AFFINE_SERVER_EXTERNAL_URL=https://affine.yourdomain.com
# position of the database data to persist
DB_DATA_LOCATION=~/.affine/self-host/postgres/pgdata
# position of the upload data(images, files, etc.) to persist
UPLOAD_LOCATION=~/.affine/self-host/storage
# position of the configuration files to persist
CONFIG_LOCATION=~/.affine/self-host/config
# database credentials
DB_USERNAME=affine
DB_PASSWORD=
DB_DATABASE=affine
+13 -23
View File
@@ -1,10 +1,10 @@
name: affine name: affine
services: services:
affine: affine:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable} image: ghcr.io/toeverything/affine:stable
container_name: affine_server container_name: affine_server
ports: ports:
- '${PORT:-3010}:3010' - '3010:3010'
depends_on: depends_on:
redis: redis:
condition: service_healthy condition: service_healthy
@@ -13,30 +13,24 @@ services:
affine_migration: affine_migration:
condition: service_completed_successfully condition: service_completed_successfully
volumes: volumes:
# custom configurations - ./data/storage:/root/.affine/storage
- ${UPLOAD_LOCATION}:/root/.affine/storage - ./config:/root/.affine/config
- ${CONFIG_LOCATION}:/root/.affine/config
env_file:
- .env
environment: environment:
- REDIS_SERVER_HOST=redis - REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine} - DATABASE_URL=postgresql://affine@postgres:5432/affine
- AFFINE_INDEXER_ENABLED=false - AFFINE_INDEXER_ENABLED=false
restart: unless-stopped restart: unless-stopped
affine_migration: affine_migration:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable} image: ghcr.io/toeverything/affine:stable
container_name: affine_migration_job container_name: affine_migration_job
volumes: volumes:
# custom configurations - ./data/storage:/root/.affine/storage
- ${UPLOAD_LOCATION}:/root/.affine/storage - ./config:/root/.affine/config
- ${CONFIG_LOCATION}:/root/.affine/config
command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js'] command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
env_file:
- .env
environment: environment:
- REDIS_SERVER_HOST=redis - REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine} - DATABASE_URL=postgresql://affine@postgres:5432/affine
- AFFINE_INDEXER_ENABLED=false - AFFINE_INDEXER_ENABLED=false
depends_on: depends_on:
postgres: postgres:
@@ -58,18 +52,14 @@ services:
image: pgvector/pgvector:pg16 image: pgvector/pgvector:pg16
container_name: affine_postgres container_name: affine_postgres
volumes: volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data - ./data/postgres:/var/lib/postgresql/data
environment: environment:
POSTGRES_USER: ${DB_USERNAME} POSTGRES_USER: affine
POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: affine
POSTGRES_DB: ${DB_DATABASE:-affine}
POSTGRES_INITDB_ARGS: '--data-checksums' POSTGRES_INITDB_ARGS: '--data-checksums'
# you better set a password for you database
# or you may add 'POSTGRES_HOST_AUTH_METHOD=trust' to ignore postgres security policy
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
healthcheck: healthcheck:
test: test: ['CMD', 'pg_isready', '-U', 'affine', '-d', 'affine']
['CMD', 'pg_isready', '-U', "${DB_USERNAME}", '-d', "${DB_DATABASE:-affine}"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
+14
View File
@@ -0,0 +1,14 @@
{
"$schema": "https://github.com/toeverything/affine/releases/latest/download/config.schema.json",
"server": {
"name": "AFFiNE Self-hosted",
"externalUrl": "http://localhost:3010"
},
"copilot": {
"enabled": true,
"byok": {
"enabled": true,
"allowCustomEndpoint": true
}
}
}
+4 -4
View File
@@ -1140,17 +1140,17 @@
"properties": { "properties": {
"enabled": { "enabled": {
"type": "boolean", "type": "boolean",
"description": "Whether to enable the copilot plugin. <br> Document: <a href=\"https://docs.affine.pro/self-host-affine/administer/ai\" target=\"_blank\">https://docs.affine.pro/self-host-affine/administer/ai</a>\n@default false", "description": "Enable AI features. Workspace owners configure provider keys in Workspace Settings → Integrations → AI BYOK.\n@default false",
"default": false "default": false
}, },
"byok.enabled": { "byok.enabled": {
"type": "boolean", "type": "boolean",
"description": "Whether to enable workspace BYOK.\n@default true", "description": "Allow workspace owners and admins to configure AI provider keys through AI BYOK.\n@default true",
"default": true "default": true
}, },
"byok.allowedProviders": { "byok.allowedProviders": {
"type": "array", "type": "array",
"description": "The allowlist for workspace BYOK providers.\n@default [\"openai\",\"anthropic\",\"gemini\",\"fal\"]", "description": "AI providers that workspace owners and admins may add through AI BYOK.\n@default [\"openai\",\"anthropic\",\"gemini\",\"fal\"]",
"default": [ "default": [
"openai", "openai",
"anthropic", "anthropic",
@@ -1160,7 +1160,7 @@
}, },
"byok.allowCustomEndpoint": { "byok.allowCustomEndpoint": {
"type": "boolean", "type": "boolean",
"description": "Whether workspace BYOK custom endpoints are accepted.\n@default false", "description": "Allow AI BYOK keys to use a custom provider endpoint.\n@default false",
"default": false "default": false
}, },
"byok.allowPrivateEndpoint": { "byok.allowPrivateEndpoint": {
+1 -1
View File
@@ -413,7 +413,7 @@ jobs:
- name: Copy Selfhost Release Files - name: Copy Selfhost Release Files
run: | run: |
cp ./.docker/selfhost/compose.yml ./release/docker-compose.yml cp ./.docker/selfhost/compose.yml ./release/docker-compose.yml
cp ./.docker/selfhost/.env.example ./release/.env.example cp ./.docker/selfhost/config.json.example ./release/config.json.example
cp ./.docker/selfhost/schema.json ./release/config.schema.json cp ./.docker/selfhost/schema.json ./release/config.schema.json
- name: Generate Release yml - name: Generate Release yml
run: | run: |
@@ -217,21 +217,21 @@ declare global {
defineModuleConfig('copilot', { defineModuleConfig('copilot', {
enabled: { enabled: {
desc: 'Whether to enable the copilot plugin. <br> Document: <a href="https://docs.affine.pro/self-host-affine/administer/ai" target="_blank">https://docs.affine.pro/self-host-affine/administer/ai</a>', desc: 'Enable AI features. Workspace owners configure provider keys in Workspace Settings → Integrations → AI BYOK.',
default: false, default: false,
}, },
'byok.enabled': { 'byok.enabled': {
desc: 'Whether to enable workspace BYOK.', desc: 'Allow workspace owners and admins to configure AI provider keys through AI BYOK.',
default: true, default: true,
shape: z.boolean(), shape: z.boolean(),
}, },
'byok.allowedProviders': { 'byok.allowedProviders': {
desc: 'The allowlist for workspace BYOK providers.', desc: 'AI providers that workspace owners and admins may add through AI BYOK.',
default: ['openai', 'anthropic', 'gemini', 'fal'], default: ['openai', 'anthropic', 'gemini', 'fal'],
shape: z.array(z.enum(['openai', 'anthropic', 'gemini', 'fal'])), shape: z.array(z.enum(['openai', 'anthropic', 'gemini', 'fal'])),
}, },
'byok.allowCustomEndpoint': { 'byok.allowCustomEndpoint': {
desc: 'Whether workspace BYOK custom endpoints are accepted.', desc: 'Allow AI BYOK keys to use a custom provider endpoint.',
default: false, default: false,
shape: z.boolean(), shape: z.boolean(),
}, },
+6 -4
View File
@@ -33,9 +33,6 @@ export const Workspaces = lazy(
export const Queue = lazy( export const Queue = lazy(
() => import(/* webpackChunkName: "queue" */ './modules/queue') () => import(/* webpackChunkName: "queue" */ './modules/queue')
); );
export const AI = lazy(
() => import(/* webpackChunkName: "ai" */ './modules/ai')
);
export const About = lazy( export const About = lazy(
() => import(/* webpackChunkName: "about" */ './modules/about') () => import(/* webpackChunkName: "about" */ './modules/about')
); );
@@ -131,7 +128,12 @@ export const App = () => {
} }
/> />
<Route path={`${ROUTES.admin.queue}/*`} element={<Queue />} /> <Route path={`${ROUTES.admin.queue}/*`} element={<Queue />} />
<Route path={ROUTES.admin.ai} element={<AI />} /> <Route
path={ROUTES.admin.ai}
element={
<Navigate to={ROUTES.admin.settings.index} replace />
}
/>
<Route path={ROUTES.admin.about} element={<About />} /> <Route path={ROUTES.admin.about} element={<About />} />
<Route <Route
path={ROUTES.admin.settings.index} path={ROUTES.admin.settings.index}
+4 -4
View File
@@ -367,19 +367,19 @@
"copilot": { "copilot": {
"enabled": { "enabled": {
"type": "Boolean", "type": "Boolean",
"desc": "Whether to enable the copilot plugin. <br> Document: <a href=\"https://docs.affine.pro/self-host-affine/administer/ai\" target=\"_blank\">https://docs.affine.pro/self-host-affine/administer/ai</a>" "desc": "Enable AI features. Workspace owners configure provider keys in Workspace Settings → Integrations → AI BYOK."
}, },
"byok.enabled": { "byok.enabled": {
"type": "Boolean", "type": "Boolean",
"desc": "Whether to enable workspace BYOK." "desc": "Allow workspace owners and admins to configure AI provider keys through AI BYOK."
}, },
"byok.allowedProviders": { "byok.allowedProviders": {
"type": "Array", "type": "Array",
"desc": "The allowlist for workspace BYOK providers." "desc": "AI providers that workspace owners and admins may add through AI BYOK."
}, },
"byok.allowCustomEndpoint": { "byok.allowCustomEndpoint": {
"type": "Boolean", "type": "Boolean",
"desc": "Whether workspace BYOK custom endpoints are accepted." "desc": "Allow AI BYOK keys to use a custom provider endpoint."
}, },
"byok.allowPrivateEndpoint": { "byok.allowPrivateEndpoint": {
"type": "Boolean", "type": "Boolean",
@@ -1,50 +0,0 @@
import { Switch } from '@affine/admin/components/ui/switch';
import { cn } from '@affine/admin/utils';
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
import { useState } from 'react';
import { Header } from '../header';
function AiPage() {
const [enableAi, setEnableAi] = useState(false);
return (
<div className="h-dvh flex-1 flex-col flex">
<Header title="AI" />
<ScrollAreaPrimitive.Root
className={cn('relative overflow-hidden w-full')}
>
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit] [&>div]:!block">
<div className="p-6 max-w-3xl mx-auto">
<div className="text-[20px]">AI</div>
<div className="flex justify-between items-center">
<div>
<p className="text-sm font-medium mt-6">Enable AI</p>
<p className="text-sm text-muted-foreground mt-1">
AI functionality is not currently supported. Self-hosted AI
support is in progress.
</p>
</div>
<Switch
checked={enableAi}
onCheckedChange={setEnableAi}
disabled={true}
/>
</div>
</div>
</ScrollAreaPrimitive.Viewport>
<ScrollAreaPrimitive.ScrollAreaScrollbar
className={cn(
'flex touch-none select-none transition-colors',
'h-full w-2.5 border-l border-l-transparent p-[1px]'
)}
>
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
</ScrollAreaPrimitive.ScrollAreaScrollbar>
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
</div>
);
}
export { AiPage as Component };
@@ -1,69 +0,0 @@
import { Button } from '@affine/admin/components/ui/button';
import { Input } from '@affine/admin/components/ui/input';
import { Label } from '@affine/admin/components/ui/label';
import { Separator } from '@affine/admin/components/ui/separator';
import { useState } from 'react';
export function Keys() {
const [openAIKey, setOpenAIKey] = useState('');
const [falAIKey, setFalAIKey] = useState('');
const [unsplashKey, setUnsplashKey] = useState('');
return (
<div className="flex flex-col h-full gap-3 py-5 px-6 w-full">
<div className="flex items-center">
<span className="text-xl font-semibold">Keys</span>
</div>
<div className="flex-grow overflow-y-auto space-y-[10px]">
<div className="flex flex-col rounded-md border py-4 gap-4">
<div className="px-5 space-y-3">
<Label className="text-sm font-medium">OpenAI Key</Label>
<div className="flex items-center gap-2">
<Input
type="text"
className="py-2 px-3 text-base font-normal placeholder:opacity-50"
value={openAIKey}
placeholder="sk-xxxxxxxxxxxxx-xxxxxxxxxxxxxx"
onChange={e => setOpenAIKey(e.target.value)}
/>
<Button disabled>Save</Button>
</div>
</div>
<Separator />
<div className="px-5 space-y-3">
<Label className="text-sm font-medium">Fal.AI Key</Label>
<div className="flex items-center gap-2">
<Input
type="email"
className="py-2 px-3 ext-base font-normal placeholder:opacity-50"
value={falAIKey}
placeholder="00000000-0000-0000-00000000:xxxxxxxxxxxxxxxxx"
onChange={e => setFalAIKey(e.target.value)}
/>
<Button disabled>Save</Button>
</div>
</div>
<Separator />
<div className="px-5 space-y-3">
<Label className="text-sm font-medium">Unsplash Key</Label>
<div className="flex items-center gap-2">
<Input
type="password"
className="py-2 px-3 ext-base font-normal placeholder:opacity-50"
value={unsplashKey}
placeholder="00000000-0000-0000-00000000:xxxxxxxxxxxxxxxxx"
onChange={e => setUnsplashKey(e.target.value)}
/>
<Button disabled>Save</Button>
</div>
</div>
<Separator />
<div className="px-5 space-y-3 text-sm font-normal text-muted-foreground">
Custom API keys may not perform as expected. AFFiNE does not
guarantee results when using custom API keys.
</div>
</div>
</div>
</div>
);
}
@@ -58,12 +58,6 @@ export function Nav({ isCollapsed = false }: NavProps) {
label="Queue" label="Queue"
isCollapsed={isCollapsed} isCollapsed={isCollapsed}
/> />
{/* <NavItem
to="/admin/ai"
icon={<AiOutlineIcon fontSize={20} />}
label="AI"
isCollapsed={isCollapsed}
/> */}
<SettingsItem isCollapsed={isCollapsed} /> <SettingsItem isCollapsed={isCollapsed} />
<NavItem <NavItem
to={ROUTES.admin.about} to={ROUTES.admin.about}
@@ -147,34 +147,19 @@ export const KNOWN_CONFIG_GROUPS = [
fields: ['providers.google', 'providers.github', 'providers.oidc'], fields: ['providers.google', 'providers.github', 'providers.oidc'],
} as ConfigGroup<'oauth'>, } as ConfigGroup<'oauth'>,
{ {
name: 'AI', name: 'AI BYOK',
module: 'copilot', module: 'copilot',
fields: [ fields: [
'enabled',
'providers.openai',
'providers.gemini',
'providers.anthropic',
'providers.fal',
'unsplash',
'exa',
{ {
key: 'storage', key: 'enabled',
desc: 'The storage provider for copilot blobs', desc: 'Enable AI features. Workspace owners configure provider keys in Workspace Settings → Integrations → AI BYOK.',
sub: 'provider',
type: 'Enum',
options: ['fs', 'aws-s3', 'cloudflare-r2'],
}, },
'byok.enabled',
'byok.allowedProviders',
'byok.allowCustomEndpoint',
{ {
key: 'storage', key: 'byok.allowPrivateEndpoint',
sub: 'bucket', desc: 'Allow workspace owners and admins to connect BYOK providers on private network endpoints. Only enable this for trusted workspaces.',
type: 'String',
desc: 'The bucket name for copilot blobs storage',
},
{
key: 'storage',
sub: 'config',
type: 'JSON',
desc: 'The S3 compatible config for the storage provider (endpoint/region/credentials).',
}, },
], ],
} as ConfigGroup<'copilot'>, } as ConfigGroup<'copilot'>,