vault backup: 2025-12-29 16:59:55
This commit is contained in:
Vendored
+15
-5
@@ -13,7 +13,7 @@
|
|||||||
"azureOpenAIApiVersion": "",
|
"azureOpenAIApiVersion": "",
|
||||||
"azureOpenAIApiEmbeddingDeploymentName": "",
|
"azureOpenAIApiEmbeddingDeploymentName": "",
|
||||||
"googleApiKey": "",
|
"googleApiKey": "",
|
||||||
"openRouterAiApiKey": "",
|
"openRouterAiApiKey": "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",
|
||||||
"xaiApiKey": "",
|
"xaiApiKey": "",
|
||||||
"mistralApiKey": "",
|
"mistralApiKey": "",
|
||||||
"deepseekApiKey": "",
|
"deepseekApiKey": "",
|
||||||
@@ -186,8 +186,8 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"isBuiltIn": true,
|
"isBuiltIn": true,
|
||||||
"capabilities": [
|
"capabilities": [
|
||||||
"reasoning",
|
"vision",
|
||||||
"vision"
|
"reasoning"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -245,14 +245,14 @@
|
|||||||
"name": "deepseek-ai/DeepSeek-V3",
|
"name": "deepseek-ai/DeepSeek-V3",
|
||||||
"provider": "siliconflow",
|
"provider": "siliconflow",
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"isBuiltIn": false,
|
"isBuiltIn": true,
|
||||||
"baseUrl": "https://api.siliconflow.com/v1"
|
"baseUrl": "https://api.siliconflow.com/v1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "deepseek-ai/DeepSeek-R1",
|
"name": "deepseek-ai/DeepSeek-R1",
|
||||||
"provider": "siliconflow",
|
"provider": "siliconflow",
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"isBuiltIn": false,
|
"isBuiltIn": true,
|
||||||
"baseUrl": "https://api.siliconflow.com/v1",
|
"baseUrl": "https://api.siliconflow.com/v1",
|
||||||
"capabilities": [
|
"capabilities": [
|
||||||
"reasoning"
|
"reasoning"
|
||||||
@@ -271,6 +271,16 @@
|
|||||||
],
|
],
|
||||||
"stream": true,
|
"stream": true,
|
||||||
"displayName": "kimi"
|
"displayName": "kimi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "deepseek/deepseek-v3.2",
|
||||||
|
"provider": "openrouterai",
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "openai/gpt-5.1-codex",
|
||||||
|
"provider": "openrouterai",
|
||||||
|
"enabled": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"activeEmbeddingModels": [
|
"activeEmbeddingModels": [
|
||||||
|
|||||||
Vendored
+28
-24
@@ -11,10 +11,14 @@
|
|||||||
"id": "f8db624785bdfc00",
|
"id": "f8db624785bdfc00",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "empty",
|
"type": "markdown",
|
||||||
"state": {},
|
"state": {
|
||||||
|
"file": "100-project/Infrastructure/Services/Soft Serve Git.md",
|
||||||
|
"mode": "source",
|
||||||
|
"source": false
|
||||||
|
},
|
||||||
"icon": "lucide-file",
|
"icon": "lucide-file",
|
||||||
"title": "New tab"
|
"title": "Soft Serve Git"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -100,7 +104,7 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "backlink",
|
"type": "backlink",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "100-project/Work/市发改委/deploy.md",
|
"file": "100-project/Infrastructure/Services/Soft Serve Git.md",
|
||||||
"collapseAll": false,
|
"collapseAll": false,
|
||||||
"extraContext": false,
|
"extraContext": false,
|
||||||
"sortOrder": "alphabetical",
|
"sortOrder": "alphabetical",
|
||||||
@@ -110,7 +114,7 @@
|
|||||||
"unlinkedCollapsed": true
|
"unlinkedCollapsed": true
|
||||||
},
|
},
|
||||||
"icon": "links-coming-in",
|
"icon": "links-coming-in",
|
||||||
"title": "Backlinks for deploy"
|
"title": "Backlinks for Soft Serve Git"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -119,12 +123,12 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "outgoing-link",
|
"type": "outgoing-link",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "100-project/Work/市发改委/deploy.md",
|
"file": "100-project/Infrastructure/Services/Soft Serve Git.md",
|
||||||
"linksCollapsed": false,
|
"linksCollapsed": false,
|
||||||
"unlinkedCollapsed": true
|
"unlinkedCollapsed": true
|
||||||
},
|
},
|
||||||
"icon": "links-going-out",
|
"icon": "links-going-out",
|
||||||
"title": "Outgoing links from deploy"
|
"title": "Outgoing links from Soft Serve Git"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -133,13 +137,13 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "outline",
|
"type": "outline",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "Clippings/foxcode - NEW CLI.md",
|
"file": "100-project/Infrastructure/Services/Soft Serve Git.md",
|
||||||
"followCursor": false,
|
"followCursor": false,
|
||||||
"showSearch": false,
|
"showSearch": false,
|
||||||
"searchQuery": ""
|
"searchQuery": ""
|
||||||
},
|
},
|
||||||
"icon": "lucide-list",
|
"icon": "lucide-list",
|
||||||
"title": "Outline of foxcode - NEW CLI"
|
"title": "Outline of Soft Serve Git"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -181,16 +185,6 @@
|
|||||||
"title": "advanced-tables-toolbar"
|
"title": "advanced-tables-toolbar"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "cc04ddc44da03907",
|
|
||||||
"type": "leaf",
|
|
||||||
"state": {
|
|
||||||
"type": "copilot-chat-view",
|
|
||||||
"state": {},
|
|
||||||
"icon": "message-square",
|
|
||||||
"title": "Copilot"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "e3e8a914deed352c",
|
"id": "e3e8a914deed352c",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
@@ -220,9 +214,19 @@
|
|||||||
"icon": "git-pull-request",
|
"icon": "git-pull-request",
|
||||||
"title": "Source Control"
|
"title": "Source Control"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "60e4e408e4363dc9",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "copilot-chat-view",
|
||||||
|
"state": {},
|
||||||
|
"icon": "message-square",
|
||||||
|
"title": "Copilot"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"currentTab": 9
|
"currentTab": 8
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"direction": "horizontal",
|
"direction": "horizontal",
|
||||||
@@ -252,6 +256,10 @@
|
|||||||
},
|
},
|
||||||
"active": "ec72abdaaa8e91a6",
|
"active": "ec72abdaaa8e91a6",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
|
"2025-12-29.md",
|
||||||
|
"100-project/Infrastructure/Services/Soft Serve Git.md",
|
||||||
|
"400-archive/_duplicates/2025-12-29-personal-refactor/openrouter.md",
|
||||||
|
"copilot/copilot-conversations/activeNote_帮我整理一下内容,找到何时的地方,把信息插入禁@20251229_163812.md",
|
||||||
"100-project/AI/Kiro/in-memoria.md",
|
"100-project/AI/Kiro/in-memoria.md",
|
||||||
"200-area/House/Moving tip.md",
|
"200-area/House/Moving tip.md",
|
||||||
"200-area/House/House.md",
|
"200-area/House/House.md",
|
||||||
@@ -276,10 +284,6 @@
|
|||||||
"100-project/Home-Automation/zigbee2mqtt.md",
|
"100-project/Home-Automation/zigbee2mqtt.md",
|
||||||
"100-project/Home-Automation/esphome.md",
|
"100-project/Home-Automation/esphome.md",
|
||||||
"100-project/Home-Automation/mopidy.md",
|
"100-project/Home-Automation/mopidy.md",
|
||||||
"100-project/Home-Automation/data.md",
|
|
||||||
"100-project/Home-Automation/WAQI.md",
|
|
||||||
"100-project/Home-Automation/Storage.md",
|
|
||||||
"100-project/Home-Automation/Sonoff ZBDongle E.md",
|
|
||||||
"100-project/Home-Automation/Hardware",
|
"100-project/Home-Automation/Hardware",
|
||||||
"100-project/Home-Automation/Config",
|
"100-project/Home-Automation/Config",
|
||||||
"100-project/Home-Automation",
|
"100-project/Home-Automation",
|
||||||
|
|||||||
@@ -29,3 +29,135 @@
|
|||||||
"event_logs:sources:opened": {"key":"sources:opened","ct":34,"first_at":1766987105710,"last_at":1766994065238,"class_name":"EventLog","event_sources":{"active-leaf-change":34}},
|
"event_logs:sources:opened": {"key":"sources:opened","ct":34,"first_at":1766987105710,"last_at":1766994065238,"class_name":"EventLog","event_sources":{"active-leaf-change":34}},
|
||||||
"event_logs:sources:opened": {"key":"sources:opened","ct":35,"first_at":1766987105710,"last_at":1766994079521,"class_name":"EventLog","event_sources":{"active-leaf-change":35}},
|
"event_logs:sources:opened": {"key":"sources:opened","ct":35,"first_at":1766987105710,"last_at":1766994079521,"class_name":"EventLog","event_sources":{"active-leaf-change":35}},
|
||||||
"event_logs:sources:opened": {"key":"sources:opened","ct":36,"first_at":1766987105710,"last_at":1766994113100,"class_name":"EventLog","event_sources":{"active-leaf-change":36}},
|
"event_logs:sources:opened": {"key":"sources:opened","ct":36,"first_at":1766987105710,"last_at":1766994113100,"class_name":"EventLog","event_sources":{"active-leaf-change":36}},
|
||||||
|
"event_logs:connections:opened": {"key":"connections:opened","ct":13,"first_at":1766986884102,"last_at":1766995048933,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":146,"first_at":1766987077711,"last_at":1766995049034,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":62,"obsidian:workspace.editor-change":84}},
|
||||||
|
"event_logs:sources:opened": {"key":"sources:opened","ct":37,"first_at":1766987105710,"last_at":1766995048629,"class_name":"EventLog","event_sources":{"active-leaf-change":37}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1181,"first_at":1766986877786,"last_at":1766995062060,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":148,"first_at":1766987077711,"last_at":1766995103190,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":62,"obsidian:workspace.editor-change":86}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":155,"first_at":1766987077711,"last_at":1766995105893,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":63,"obsidian:workspace.editor-change":92}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":156,"first_at":1766987077711,"last_at":1766995107436,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":64,"obsidian:workspace.editor-change":92}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":163,"first_at":1766987077711,"last_at":1766995111352,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":64,"obsidian:workspace.editor-change":99}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":165,"first_at":1766987077711,"last_at":1766995112179,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":65,"obsidian:workspace.editor-change":100}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":167,"first_at":1766987077711,"last_at":1766995113630,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":65,"obsidian:workspace.editor-change":102}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1182,"first_at":1766986877786,"last_at":1766995115856,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":187,"first_at":1766987077711,"last_at":1766995118786,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":67,"obsidian:workspace.editor-change":120}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":216,"first_at":1766987077711,"last_at":1766995124615,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":70,"obsidian:workspace.editor-change":146}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":217,"first_at":1766987077711,"last_at":1766995126618,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":71,"obsidian:workspace.editor-change":146}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1183,"first_at":1766986877786,"last_at":1766995129316,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":222,"first_at":1766987077711,"last_at":1766995188105,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":71,"obsidian:workspace.editor-change":151}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":228,"first_at":1766987077711,"last_at":1766995189837,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":72,"obsidian:workspace.editor-change":156}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":236,"first_at":1766987077711,"last_at":1766995193138,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":73,"obsidian:workspace.editor-change":163}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":253,"first_at":1766987077711,"last_at":1766995197509,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":75,"obsidian:workspace.editor-change":178}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1184,"first_at":1766986877786,"last_at":1766995200731,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":270,"first_at":1766987077711,"last_at":1766995202856,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":77,"obsidian:workspace.editor-change":193}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":273,"first_at":1766987077711,"last_at":1766995204500,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":78,"obsidian:workspace.editor-change":195}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":274,"first_at":1766987077711,"last_at":1766995205996,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":79,"obsidian:workspace.editor-change":195}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1185,"first_at":1766986877786,"last_at":1766995213801,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":276,"first_at":1766987077711,"last_at":1766995315069,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":79,"obsidian:workspace.editor-change":197}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":277,"first_at":1766987077711,"last_at":1766995316055,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":79,"obsidian:workspace.editor-change":198}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":287,"first_at":1766987077711,"last_at":1766995319726,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":80,"obsidian:workspace.editor-change":207}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":288,"first_at":1766987077711,"last_at":1766995320610,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":80,"obsidian:workspace.editor-change":208}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":295,"first_at":1766987077711,"last_at":1766995322444,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":81,"obsidian:workspace.editor-change":214}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":314,"first_at":1766987077711,"last_at":1766995327058,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":83,"obsidian:workspace.editor-change":231}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1186,"first_at":1766986877786,"last_at":1766995328067,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":333,"first_at":1766987077711,"last_at":1766995331241,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":85,"obsidian:workspace.editor-change":248}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":346,"first_at":1766987077711,"last_at":1766995334654,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":87,"obsidian:workspace.editor-change":259}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":361,"first_at":1766987077711,"last_at":1766995338674,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":88,"obsidian:workspace.editor-change":273}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":364,"first_at":1766987077711,"last_at":1766995339865,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":89,"obsidian:workspace.editor-change":275}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1187,"first_at":1766986877786,"last_at":1766995341374,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":366,"first_at":1766987077711,"last_at":1766995341869,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":90,"obsidian:workspace.editor-change":276}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":367,"first_at":1766987077711,"last_at":1766995348857,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":90,"obsidian:workspace.editor-change":277}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":368,"first_at":1766987077711,"last_at":1766995350861,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":91,"obsidian:workspace.editor-change":277}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":369,"first_at":1766987077711,"last_at":1766995352140,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":91,"obsidian:workspace.editor-change":278}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1188,"first_at":1766986877786,"last_at":1766995354888,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":375,"first_at":1766987077711,"last_at":1766995355293,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":92,"obsidian:workspace.editor-change":283}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":376,"first_at":1766987077711,"last_at":1766995356699,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":93,"obsidian:workspace.editor-change":283}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1189,"first_at":1766986877786,"last_at":1766995368048,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":377,"first_at":1766987077711,"last_at":1766995367512,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":93,"obsidian:workspace.editor-change":284}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":379,"first_at":1766987077711,"last_at":1766995369515,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":94,"obsidian:workspace.editor-change":285}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":380,"first_at":1766987077711,"last_at":1766995371485,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":94,"obsidian:workspace.editor-change":286}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":381,"first_at":1766987077711,"last_at":1766995373488,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":95,"obsidian:workspace.editor-change":286}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1190,"first_at":1766986877786,"last_at":1766995382413,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":462,"first_at":1766987077711,"last_at":1766995955889,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":97,"obsidian:workspace.editor-change":365}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":463,"first_at":1766987077711,"last_at":1766995957659,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":98,"obsidian:workspace.editor-change":365}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":466,"first_at":1766987077711,"last_at":1766995959985,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":98,"obsidian:workspace.editor-change":368}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":467,"first_at":1766987077711,"last_at":1766995961035,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":99,"obsidian:workspace.editor-change":368}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1191,"first_at":1766986877786,"last_at":1766995964255,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":468,"first_at":1766987077711,"last_at":1766995969210,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":99,"obsidian:workspace.editor-change":369}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":470,"first_at":1766987077711,"last_at":1766995971214,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":100,"obsidian:workspace.editor-change":370}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1192,"first_at":1766986877786,"last_at":1766995982225,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":476,"first_at":1766987077711,"last_at":1766996012870,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":101,"obsidian:workspace.editor-change":375}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":490,"first_at":1766987077711,"last_at":1766996015409,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":102,"obsidian:workspace.editor-change":388}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":493,"first_at":1766987077711,"last_at":1766996017654,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":103,"obsidian:workspace.editor-change":390}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":496,"first_at":1766987077711,"last_at":1766996018867,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":103,"obsidian:workspace.editor-change":393}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":505,"first_at":1766987077711,"last_at":1766996021854,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":105,"obsidian:workspace.editor-change":400}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1193,"first_at":1766986877786,"last_at":1766996023644,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":507,"first_at":1766987077711,"last_at":1766996024281,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":105,"obsidian:workspace.editor-change":402}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":508,"first_at":1766987077711,"last_at":1766996025866,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":106,"obsidian:workspace.editor-change":402}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1194,"first_at":1766986877786,"last_at":1766996037113,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":511,"first_at":1766987077711,"last_at":1766996802549,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":106,"obsidian:workspace.editor-change":405}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":512,"first_at":1766987077711,"last_at":1766996804152,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":107,"obsidian:workspace.editor-change":405}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1195,"first_at":1766986877786,"last_at":1766996815161,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":513,"first_at":1766987077711,"last_at":1766996868700,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":107,"obsidian:workspace.editor-change":406}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":555,"first_at":1766987077711,"last_at":1766996878168,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":111,"obsidian:workspace.editor-change":444}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":559,"first_at":1766987077711,"last_at":1766996880075,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":112,"obsidian:workspace.editor-change":447}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1196,"first_at":1766986877786,"last_at":1766996881773,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":560,"first_at":1766987077711,"last_at":1766996881346,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":113,"obsidian:workspace.editor-change":447}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":561,"first_at":1766987077711,"last_at":1766996900002,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":113,"obsidian:workspace.editor-change":448}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":562,"first_at":1766987077711,"last_at":1766996902006,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":114,"obsidian:workspace.editor-change":448}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":563,"first_at":1766987077711,"last_at":1766996903241,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":114,"obsidian:workspace.editor-change":449}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":564,"first_at":1766987077711,"last_at":1766996905245,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":115,"obsidian:workspace.editor-change":449}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1197,"first_at":1766986877786,"last_at":1766996913017,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":575,"first_at":1766987077711,"last_at":1766996919823,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":116,"obsidian:workspace.editor-change":459}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":581,"first_at":1766987077711,"last_at":1766996923294,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":117,"obsidian:workspace.editor-change":464}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":582,"first_at":1766987077711,"last_at":1766996924797,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":118,"obsidian:workspace.editor-change":464}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":584,"first_at":1766987077711,"last_at":1766996927119,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":118,"obsidian:workspace.editor-change":466}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":585,"first_at":1766987077711,"last_at":1766996928665,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":119,"obsidian:workspace.editor-change":466}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1198,"first_at":1766986877786,"last_at":1766996930833,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":587,"first_at":1766987077711,"last_at":1766997379495,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":119,"obsidian:workspace.editor-change":468}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":588,"first_at":1766987077711,"last_at":1766997381274,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":120,"obsidian:workspace.editor-change":468}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1199,"first_at":1766986877786,"last_at":1766997392326,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":589,"first_at":1766987077711,"last_at":1766997391650,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":120,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":590,"first_at":1766987077711,"last_at":1766997393657,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":121,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1200,"first_at":1766986877786,"last_at":1766997410969,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:created": {"key":"sources:created","ct":356,"first_at":1766987075389,"last_at":1766997492981,"class_name":"EventLog","event_sources":{"obsidian:vault.create":356}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":591,"first_at":1766987077711,"last_at":1766997492989,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":122,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1201,"first_at":1766986877786,"last_at":1766997505983,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":592,"first_at":1766987077711,"last_at":1766997539301,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":123,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1202,"first_at":1766986877786,"last_at":1766997552302,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":593,"first_at":1766987077711,"last_at":1766997560976,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":124,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1203,"first_at":1766986877786,"last_at":1766997573978,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":594,"first_at":1766987077711,"last_at":1766997639241,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":125,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":595,"first_at":1766987077711,"last_at":1766997645789,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":126,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1204,"first_at":1766986877786,"last_at":1766997652247,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":596,"first_at":1766987077711,"last_at":1766997670005,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":127,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1205,"first_at":1766986877786,"last_at":1766997683007,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":597,"first_at":1766987077711,"last_at":1766997832809,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":128,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1206,"first_at":1766986877786,"last_at":1766997845813,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:opened": {"key":"sources:opened","ct":38,"first_at":1766987105710,"last_at":1766997929653,"class_name":"EventLog","event_sources":{"active-leaf-change":38}},
|
||||||
|
"event_logs:sources:opened": {"key":"sources:opened","ct":39,"first_at":1766987105710,"last_at":1766998127248,"class_name":"EventLog","event_sources":{"active-leaf-change":39}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":598,"first_at":1766987077711,"last_at":1766998178862,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":129,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1207,"first_at":1766986877786,"last_at":1766998191872,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":599,"first_at":1766987077711,"last_at":1766998198884,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":130,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1208,"first_at":1766986877786,"last_at":1766998211891,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":600,"first_at":1766987077711,"last_at":1766998214766,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":131,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1209,"first_at":1766986877786,"last_at":1766998227774,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":601,"first_at":1766987077711,"last_at":1766998369207,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":132,"obsidian:workspace.editor-change":469}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1210,"first_at":1766986877786,"last_at":1766998382238,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:created": {"key":"sources:created","ct":357,"first_at":1766987075389,"last_at":1766998533332,"class_name":"EventLog","event_sources":{"obsidian:vault.create":357}},
|
||||||
|
"event_logs:sources:opened": {"key":"sources:opened","ct":40,"first_at":1766987105710,"last_at":1766998533384,"class_name":"EventLog","event_sources":{"active-leaf-change":40}},
|
||||||
|
"event_logs:event_log:first": {"key":"event_log:first","ct":4,"first_at":1766994008577,"last_at":1766998541874,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:renamed": {"key":"sources:renamed","ct":1,"first_at":1766998541874,"last_at":1766998541874,"class_name":"EventLog","event_sources":{"obsidian:vault.rename":1}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1212,"first_at":1766986877786,"last_at":1766998554876,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":602,"first_at":1766987077711,"last_at":1766998611773,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":132,"obsidian:workspace.editor-change":470}},
|
||||||
|
"event_logs:sources:opened": {"key":"sources:opened","ct":41,"first_at":1766987105710,"last_at":1766998610941,"class_name":"EventLog","event_sources":{"active-leaf-change":41}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":603,"first_at":1766987077711,"last_at":1766998613777,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":133,"obsidian:workspace.editor-change":470}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":604,"first_at":1766987077711,"last_at":1766998616824,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":133,"obsidian:workspace.editor-change":471}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":605,"first_at":1766987077711,"last_at":1766998618739,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":134,"obsidian:workspace.editor-change":471}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1213,"first_at":1766986877786,"last_at":1766998624778,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":606,"first_at":1766987077711,"last_at":1766998642209,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":134,"obsidian:workspace.editor-change":472}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":607,"first_at":1766987077711,"last_at":1766998644213,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":135,"obsidian:workspace.editor-change":472}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1214,"first_at":1766986877786,"last_at":1766998655214,"class_name":"EventLog"},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":608,"first_at":1766987077711,"last_at":1766998672626,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":135,"obsidian:workspace.editor-change":473}},
|
||||||
|
"event_logs:sources:modified": {"key":"sources:modified","ct":609,"first_at":1766987077711,"last_at":1766998674635,"class_name":"EventLog","event_sources":{"obsidian:vault.modify":136,"obsidian:workspace.editor-change":473}},
|
||||||
|
"event_logs:sources:imported": {"key":"sources:imported","ct":1215,"first_at":1766986877786,"last_at":1766998685630,"class_name":"EventLog"},
|
||||||
@@ -0,0 +1,445 @@
|
|||||||
|
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
# Soft Serve 安装指南(Docker Compose + Traefik TCP + CNAME)
|
||||||
|
|
||||||
|
## 1. 目标与最终形态
|
||||||
|
|
||||||
|
- 域名:`repo.windy.me`
|
||||||
|
- DNS:`repo.windy.me` **CNAME → `us2.wsvc.info`**
|
||||||
|
- 部署主机:`us2.wsvc.info` 对应的 VPS(本文称 "us2")
|
||||||
|
- Soft Serve 镜像:`ghcr.io/charmbracelet/soft-serve:latest`
|
||||||
|
- 数据持久化:宿主机 `./data` → 容器 `/var/lib/soft-serve`
|
||||||
|
- 访问方式:SSH(Soft Serve SSH 服务端口为容器内 `23231`)
|
||||||
|
- 暴露方式(推荐):Traefik TCP entrypoint `ssh` 监听宿主机 `2222`,转发到容器 `23231`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 前置条件清单
|
||||||
|
|
||||||
|
### 2.1 DNS(CNAME)
|
||||||
|
|
||||||
|
你已设置:
|
||||||
|
- `repo.windy.me` CNAME → `us2.wsvc.info`
|
||||||
|
|
||||||
|
关键含义:
|
||||||
|
- 用户访问 `repo.windy.me` 时,最终会解析到 **us2 的公网 IP**
|
||||||
|
- 只要 us2 上对外开放 SSH 入口端口(示例:2222),访问就成立
|
||||||
|
|
||||||
|
建议验证(任意机器):
|
||||||
|
```bash
|
||||||
|
dig +short repo.windy.me CNAME
|
||||||
|
dig +short repo.windy.me A
|
||||||
|
````
|
||||||
|
|
||||||
|
### 2.2 网络与防火墙
|
||||||
|
|
||||||
|
在 us2 上确保对外放行你用于 Soft Serve SSH 的端口(示例 2222):
|
||||||
|
|
||||||
|
- 入站允许:TCP 2222
|
||||||
|
|
||||||
|
### 2.3 Traefik 已存在并使用外部网络
|
||||||
|
|
||||||
|
你当前 compose 使用:
|
||||||
|
|
||||||
|
- external network:`vw-net`
|
||||||
|
|
||||||
|
确保 Traefik 容器也在同一个 `vw-net` 网络内。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 准备目录与配置文件
|
||||||
|
|
||||||
|
在 us2 上:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /opt/soft-serve
|
||||||
|
cd /opt/soft-serve
|
||||||
|
mkdir -p data
|
||||||
|
```
|
||||||
|
|
||||||
|
最终结构:
|
||||||
|
|
||||||
|
```
|
||||||
|
/opt/soft-serve/
|
||||||
|
compose.yml
|
||||||
|
.env
|
||||||
|
data/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 准备初始化管理员公钥(必须)
|
||||||
|
|
||||||
|
Soft Serve 首次启动会根据环境变量写入初始管理员 key。你已经验证的公钥写法如下(单行):
|
||||||
|
|
||||||
|
`.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
SOFT_SERVE_INITIAL_ADMIN_KEYS=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE9irsGu03p+1xrwIfzrzjGZCcExJ/XFEgkqsgfEN70j windy@windy-mbp
|
||||||
|
```
|
||||||
|
|
||||||
|
注意事项:
|
||||||
|
|
||||||
|
- 必须是 **完整公钥的一整行**
|
||||||
|
- 只在 **数据目录首次初始化(空目录)** 时生效
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Docker Compose(推荐:Traefik TCP 暴露 SSH)
|
||||||
|
|
||||||
|
`compose.yml`(与你当前成功的结构一致,并保留注释):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
soft-serve:
|
||||||
|
image: ghcr.io/charmbracelet/soft-serve:latest
|
||||||
|
container_name: soft-serve
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
SOFT_SERVE_DATA_PATH: /var/lib/soft-serve
|
||||||
|
SOFT_SERVE_INITIAL_ADMIN: windy
|
||||||
|
SOFT_SERVE_INITIAL_ADMIN_KEYS: ${SOFT_SERVE_INITIAL_ADMIN_KEYS}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ./data:/var/lib/soft-serve
|
||||||
|
|
||||||
|
# 方案B:直连端口映射(不走 Traefik)
|
||||||
|
# ports:
|
||||||
|
# - "2222:23231"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- traefik.enable=true
|
||||||
|
|
||||||
|
# SSH over TCP via Traefik (entryPoint ssh -> container port 23231)
|
||||||
|
- traefik.tcp.routers.softserve-ssh.entrypoints=ssh
|
||||||
|
- traefik.tcp.routers.softserve-ssh.rule=HostSNI(`*`)
|
||||||
|
- traefik.tcp.routers.softserve-ssh.tls=false
|
||||||
|
- traefik.tcp.services.softserve-ssh.loadbalancer.server.port=23231
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
|
name: vw-net
|
||||||
|
```
|
||||||
|
|
||||||
|
### 关于 "SSH 不能走 Traefik 代理域名分流"的结论
|
||||||
|
|
||||||
|
- SSH 不是 HTTP;Traefik 在这里是 **TCP 转发**
|
||||||
|
- 不要使用 `HostSNI(repo.windy.me)` 之类的规则来"按域名"分流 SSH(会引发 TLS/HostSNI 相关报错)
|
||||||
|
- 最稳妥的做法就是:
|
||||||
|
- `tls=false`
|
||||||
|
- `HostSNI('*')`
|
||||||
|
- 依赖端口入口(2222)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Traefik 静态配置要求(必须有 entrypoint)
|
||||||
|
|
||||||
|
你必须在 Traefik 的静态配置中定义 `ssh` entrypoint,并监听对外端口(示例:2222)。
|
||||||
|
|
||||||
|
示例(只示意关键段):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
entryPoints:
|
||||||
|
ssh:
|
||||||
|
address: ":2222"
|
||||||
|
```
|
||||||
|
|
||||||
|
如果缺失,会出现典型错误:
|
||||||
|
|
||||||
|
- `EntryPoint doesn't exist entryPointName=ssh`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 首次启动与"只初始化一次"的规则
|
||||||
|
|
||||||
|
### 7.1 首次启动
|
||||||
|
|
||||||
|
在 `/opt/soft-serve`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
docker compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 初始化只发生一次(关键规则)
|
||||||
|
|
||||||
|
如需重新初始化(比如 `.env` 修改后不生效),必须清空数据目录:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose down
|
||||||
|
rm -rf ./data
|
||||||
|
mkdir -p ./data
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 客户端连接与"user not found"修正方法
|
||||||
|
|
||||||
|
### 8.1 强制使用指定 key(排错与首次推荐)
|
||||||
|
|
||||||
|
你最终验证成功的关键点是:**固定 key + IdentitiesOnly**。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 -p 2222 repo.windy.me info
|
||||||
|
```
|
||||||
|
|
||||||
|
若成功会输出类似:
|
||||||
|
|
||||||
|
```
|
||||||
|
Username: admin (或 windy)
|
||||||
|
Admin: true
|
||||||
|
Public keys: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 把默认用户名从 `admin` 改成 `windy`
|
||||||
|
|
||||||
|
你已成功的改名命令(注意同样要固定 key):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 -p 2222 repo.windy.me set-username windy
|
||||||
|
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 -p 2222 repo.windy.me info
|
||||||
|
```
|
||||||
|
|
||||||
|
**解释:**"user not found" 的真实根因通常不是 Soft Serve 没用户,而是 SSH 客户端未固定 key 时选用了另一把 key,导致 Soft Serve 无法把该连接映射到已存在的用户。
|
||||||
|
|
||||||
|
### 8.3 永久固化:写 `~/.ssh/config`
|
||||||
|
|
||||||
|
在本机写入:
|
||||||
|
|
||||||
|
```sshconfig
|
||||||
|
Host repo.windy.me
|
||||||
|
HostName repo.windy.me
|
||||||
|
Port 2222
|
||||||
|
User git
|
||||||
|
IdentityFile ~/.ssh/id_ed25519
|
||||||
|
IdentitiesOnly yes
|
||||||
|
```
|
||||||
|
|
||||||
|
之后即可:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh repo.windy.me info
|
||||||
|
ssh repo.windy.me repo list
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 创建仓库与 Git clone/push
|
||||||
|
|
||||||
|
### 9.1 创建仓库
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh repo.windy.me repo create test
|
||||||
|
ssh repo.windy.me repo list
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9.2 Clone(推荐写法)
|
||||||
|
|
||||||
|
写法 A(最清晰):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone ssh://repo.windy.me:2222/test.git
|
||||||
|
```
|
||||||
|
|
||||||
|
写法 B(scp 风格,依赖 ssh config 的 Port):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone repo.windy.me:test.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9.3 Push 验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd test
|
||||||
|
echo "# test" > README.md
|
||||||
|
git add .
|
||||||
|
git commit -m "init"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 常见故障排查(快速定位)
|
||||||
|
|
||||||
|
### 10.1 连接到错误端口
|
||||||
|
|
||||||
|
现象:你以为是 23231,但实际对外是 2222(由 Traefik entrypoint 决定)。
|
||||||
|
|
||||||
|
验证(在 us2 上):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ss -lntp | grep :2222
|
||||||
|
```
|
||||||
|
|
||||||
|
应看到 Traefik 监听 2222。
|
||||||
|
|
||||||
|
### 10.2 `EntryPoint doesn't exist entryPointName=ssh`
|
||||||
|
|
||||||
|
原因:Traefik 静态配置未定义 `entryPoints.ssh`。
|
||||||
|
|
||||||
|
修复:给 Traefik 增加:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
entryPoints:
|
||||||
|
ssh:
|
||||||
|
address: ":2222"
|
||||||
|
```
|
||||||
|
|
||||||
|
并重启 Traefik。
|
||||||
|
|
||||||
|
### 10.3 `Error: user not found`
|
||||||
|
|
||||||
|
高概率原因:SSH 客户端用了"另一把 key"。
|
||||||
|
|
||||||
|
修复(强制固定 key):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -vvv -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 -p 2222 repo.windy.me info
|
||||||
|
```
|
||||||
|
|
||||||
|
观察日志中是否出现:
|
||||||
|
|
||||||
|
- `Offering public key: ... id_ed25519`
|
||||||
|
- `Server accepts key: ... id_ed25519`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. 备份与恢复(生产建议)
|
||||||
|
|
||||||
|
### 11.1 需要备份的内容
|
||||||
|
|
||||||
|
Soft Serve 核心数据都在宿主机 `./data`(映射自 `/var/lib/soft-serve`):
|
||||||
|
|
||||||
|
- `soft-serve.db`(用户/设置)
|
||||||
|
- `repos/`(仓库数据,如存在)
|
||||||
|
- `ssh/`(host keys 等)
|
||||||
|
|
||||||
|
### 11.2 最简单备份命令
|
||||||
|
|
||||||
|
在 us2 上:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/soft-serve
|
||||||
|
tar -czf soft-serve-backup-$(date +%F).tar.gz ./data
|
||||||
|
```
|
||||||
|
|
||||||
|
恢复流程:
|
||||||
|
|
||||||
|
1. `docker compose down`
|
||||||
|
2. 解压覆盖 `./data`
|
||||||
|
3. `docker compose up -d`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. 推荐的"最终检查清单"
|
||||||
|
|
||||||
|
- `repo.windy.me` CNAME 指向 `us2.wsvc.info`,并能解析到 us2 IP
|
||||||
|
- us2 对外开放 TCP 2222
|
||||||
|
- Traefik 静态配置存在 `entryPoints.ssh=:2222`
|
||||||
|
- Soft Serve 数据目录持久化:`./data:/var/lib/soft-serve`
|
||||||
|
- 客户端 `~/.ssh/config` 固定 `IdentityFile` + `IdentitiesOnly yes`
|
||||||
|
- `ssh repo.windy.me info` 输出 `Username: windy` 且 `Admin: true`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录:生产级配置建议(可选)
|
||||||
|
|
||||||
|
### A.1 生产级 compose(healthcheck、日志限制、只读 filesystem、资源限制)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
soft-serve:
|
||||||
|
image: ghcr.io/charmbracelet/soft-serve:latest
|
||||||
|
container_name: soft-serve
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
SOFT_SERVE_DATA_PATH: /var/lib/soft-serve
|
||||||
|
SOFT_SERVE_INITIAL_ADMIN: windy
|
||||||
|
SOFT_SERVE_INITIAL_ADMIN_KEYS: ${SOFT_SERVE_INITIAL_ADMIN_KEYS}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ./data:/var/lib/soft-serve:rw
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- traefik.enable=true
|
||||||
|
- traefik.tcp.routers.softserve-ssh.entrypoints=ssh
|
||||||
|
- traefik.tcp.routers.softserve-ssh.rule=HostSNI(`*`)
|
||||||
|
- traefik.tcp.routers.softserve-ssh.tls=false
|
||||||
|
- traefik.tcp.services.softserve-ssh.loadbalancer.server.port=23231
|
||||||
|
|
||||||
|
# 健康检查
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "nc", "-z", "localhost", "23231"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
|
# 资源限制
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 512M
|
||||||
|
cpus: '0.5'
|
||||||
|
reservations:
|
||||||
|
memory: 256M
|
||||||
|
cpus: '0.25'
|
||||||
|
|
||||||
|
# 安全设置
|
||||||
|
read_only: true
|
||||||
|
tmpfs:
|
||||||
|
- /tmp:size=100M,mode=1777
|
||||||
|
|
||||||
|
# 日志限制
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik:
|
||||||
|
external: true
|
||||||
|
name: vw-net
|
||||||
|
```
|
||||||
|
|
||||||
|
### A.2 Traefik 静态配置片段
|
||||||
|
|
||||||
|
示例 Traefik 静态配置(`traefik.yml` 或命令行参数):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# traefik.yml 示例
|
||||||
|
entryPoints:
|
||||||
|
ssh:
|
||||||
|
address: ":2222"
|
||||||
|
|
||||||
|
api:
|
||||||
|
dashboard: true
|
||||||
|
insecure: true
|
||||||
|
|
||||||
|
providers:
|
||||||
|
docker:
|
||||||
|
endpoint: "unix:///var/run/docker.sock"
|
||||||
|
exposedByDefault: false
|
||||||
|
network: vw-net
|
||||||
|
```
|
||||||
|
|
||||||
|
或通过命令行参数:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
--entrypoints.ssh.address=:2222
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
+191
@@ -399,3 +399,194 @@ tar -czf soft-serve-backup-$(date +%F).tar.gz ./data
|
|||||||
1. **一份生产级 compose**(healthcheck、日志限制、只读 filesystem、资源限制)
|
1. **一份生产级 compose**(healthcheck、日志限制、只读 filesystem、资源限制)
|
||||||
|
|
||||||
2. **一份 Traefik 静态配置片段**(与你当前 Traefik 容器的真实配置方式对齐:file provider / command args / labels)
|
2. **一份 Traefik 静态配置片段**(与你当前 Traefik 容器的真实配置方式对齐:file provider / command args / labels)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Use user name and password for nghttpx
|
||||||
|
|
||||||
|
User name:
|
||||||
|
```
|
||||||
|
windy
|
||||||
|
```
|
||||||
|
|
||||||
|
Password:
|
||||||
|
```
|
||||||
|
meeQuan4jeinging
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
htpasswd -c ./passwords windy
|
||||||
|
```
|
||||||
|
|
||||||
|
Passwords
|
||||||
|
```
|
||||||
|
windy:$apr1$5usfjVkQ$Zsd27eX..5sZjFtRVTVjn1
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Squid. Conf
|
||||||
|
```
|
||||||
|
http_port 3128
|
||||||
|
|
||||||
|
# Define the authentication program
|
||||||
|
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords
|
||||||
|
auth_param basic realm windy private https proxy
|
||||||
|
auth_param basic children 5
|
||||||
|
auth_param basic credentialsttl 2 hours
|
||||||
|
|
||||||
|
# Define the ACL (Access Control List) for authenticated users
|
||||||
|
acl authenticated_users proxy_auth REQUIRED
|
||||||
|
|
||||||
|
# Allow access only to authenticated users
|
||||||
|
http_access allow authenticated_users
|
||||||
|
|
||||||
|
# 关闭 Via 头 (隐私保护)
|
||||||
|
via off
|
||||||
|
forwarded_for off
|
||||||
|
|
||||||
|
# 日志设置
|
||||||
|
access_log stdio:/var/log/squid/access.log combined
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Compose
|
||||||
|
```
|
||||||
|
squid:
|
||||||
|
image: ubuntu/squid:latest
|
||||||
|
container_name: squid-backend
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./squid.conf:/etc/squid/squid.conf
|
||||||
|
- ./passwords:/etc/squid/passwords:ro
|
||||||
|
- squid_cache:/var/spool/squid
|
||||||
|
command: ["squid", "-N", "-d", "1"]
|
||||||
|
networks:
|
||||||
|
- internal-net
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
You are absolutely correct to verify the documentation. I apologize for the previous error—**`nghttpx` does NOT support native Basic Authentication (username/password) for frontend clients.** The option `frontend-http-user` (and `basic-auth-file`) does not exist in the official `nghttpx` documentation.
|
||||||
|
|
||||||
|
Since your architecture is **Client -> nghttpx (TLS) -> Squid (Proxy)**, the correct place to handle authentication is in **Squid**, not `nghttpx`.
|
||||||
|
|
||||||
|
Here is the corrected, documentation-verified setup.
|
||||||
|
|
||||||
|
### 1. The Strategy
|
||||||
|
|
||||||
|
We will configure **Squid** to handle the username/password verification. `nghttpx` will simply pass the credentials (the `Proxy-Authorization` header) from the user to Squid.
|
||||||
|
|
||||||
|
### 2. Create the Password File
|
||||||
|
|
||||||
|
You need a tool like `htpasswd` (from `apache2-utils`) to create a hashed password file. Run this on your host machine:
|
||||||
|
|
||||||
|
Bash
|
||||||
|
|
||||||
|
```
|
||||||
|
# Create file 'passwords' with user 'myuser'
|
||||||
|
htpasswd -c ./passwords myuser
|
||||||
|
# Enter password when prompted
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Update `docker-compose.yml`
|
||||||
|
|
||||||
|
You need to mount this password file into the **Squid** service (not nghttpx). You also need to mount a custom `squid.conf`.
|
||||||
|
|
||||||
|
YAML
|
||||||
|
|
||||||
|
```
|
||||||
|
services:
|
||||||
|
# ... nghttpx service remains the same ...
|
||||||
|
|
||||||
|
squid:
|
||||||
|
image: ubuntu/squid:latest
|
||||||
|
container_name: squid-proxy
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./squid.conf:/etc/squid/squid.conf:ro
|
||||||
|
- ./passwords:/etc/squid/passwords:ro # Mount the password file here
|
||||||
|
networks:
|
||||||
|
- internal-net
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Create `squid.conf`
|
||||||
|
|
||||||
|
Create a `squid.conf` file in the same directory. This configuration enables Basic Authentication using the file we just created.
|
||||||
|
|
||||||
|
Code snippet
|
||||||
|
|
||||||
|
```
|
||||||
|
# Define the authentication program
|
||||||
|
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords
|
||||||
|
auth_param basic realm My Private Proxy
|
||||||
|
auth_param basic children 5
|
||||||
|
auth_param basic credentialsttl 2 hours
|
||||||
|
|
||||||
|
# Define the ACL (Access Control List) for authenticated users
|
||||||
|
acl authenticated_users proxy_auth REQUIRED
|
||||||
|
|
||||||
|
# Allow access only to authenticated users
|
||||||
|
http_access allow authenticated_users
|
||||||
|
|
||||||
|
# Deny everything else
|
||||||
|
http_access deny all
|
||||||
|
|
||||||
|
# Listen on port 3128
|
||||||
|
http_port 3128
|
||||||
|
```
|
||||||
|
|
||||||
|
_(Note: The path `/usr/lib/squid/basic_ncsa_auth` is standard for Ubuntu/Debian based Squid images. If you use Alpine, it might be `/usr/lib/squid/basic_ncsa_auth` or similar, check `apk info -L squid` if it fails)._
|
||||||
|
|
||||||
|
### 5. Clean up `nghttpx.conf`
|
||||||
|
|
||||||
|
Revert `nghttpx.conf` to its clean state (remove the invalid auth lines). `nghttpx` must be configured to pass the traffic transparently.
|
||||||
|
|
||||||
|
Code snippet
|
||||||
|
|
||||||
|
```
|
||||||
|
# nghttpx.conf
|
||||||
|
|
||||||
|
# Frontend: Listen on 3000, no TLS (Traefik handles TLS)
|
||||||
|
frontend=0.0.0.0,3000;no-tls
|
||||||
|
|
||||||
|
# Backend: Forward to Squid
|
||||||
|
backend=squid,3128
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
errorlog-file=/dev/stderr
|
||||||
|
accesslog-file=/dev/stdout
|
||||||
|
log-level=INFO
|
||||||
|
|
||||||
|
# Essential: Do NOT strip proxy headers, otherwise Squid won't see the password!
|
||||||
|
strip-incoming-x-forwarded-for=no
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Verify and Apply
|
||||||
|
|
||||||
|
1. **Restart:** `docker-compose up -d --force-recreate`
|
||||||
|
|
||||||
|
2. **Test:**
|
||||||
|
|
||||||
|
Bash
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -v -x https://us2.wsvc.info:443 -U myuser:mypassword http://google.com
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
**Why this works:**
|
||||||
|
|
||||||
|
- The client sends a request with a `Proxy-Authorization` header.
|
||||||
|
|
||||||
|
- Traefik decrypts TLS and passes it to `nghttpx`.
|
||||||
|
|
||||||
|
- `nghttpx` forwards the request (including the header) to `squid`.
|
||||||
|
|
||||||
|
- `squid` checks the header against the `/etc/squid/passwords` file.
|
||||||
|
|
||||||
|
- If valid, `squid` allows the traffic.
|
||||||
|
|
||||||
|
|
||||||
|
Would you like me to generate the `squid.conf` specifically for an **Alpine** based Squid image if you are using one to keep the image size small?
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user