[{"data":1,"prerenderedAt":6372},["ShallowReactive",2],{"published-article-paths":3,"search-navigation":348,"\u002Farticle\u002Fsync-obsidian-across-devices":421,"\u002Farticle\u002Fsync-obsidian-across-devices-surround":1941},[4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308,310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344,346],{"path":5},"\u002Fde\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":7},"\u002Fde\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":9},"\u002Fde\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":11},"\u002Fde\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":13},"\u002Fde\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":15},"\u002Fde\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":17},"\u002Fde\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":19},"\u002Fde\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":21},"\u002Fde\u002Farticle\u002Fsetup-antigravity-2",{"path":23},"\u002Fde\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":25},"\u002Fde\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":27},"\u002Fde\u002Farticle\u002Fsync-obsidian-across-devices",{"path":29},"\u002Fde\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":31},"\u002Fde\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":33},"\u002Fde\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":35},"\u002Fde\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":37},"\u002Fen\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":39},"\u002Fen\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":41},"\u002Fen\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":43},"\u002Fen\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":45},"\u002Fen\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":47},"\u002Fen\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":49},"\u002Fen\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":51},"\u002Fen\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":53},"\u002Fen\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":55},"\u002Fen\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":57},"\u002Fen\u002Farticle\u002Fsetup-antigravity-2",{"path":59},"\u002Fen\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":61},"\u002Fen\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":63},"\u002Fen\u002Farticle\u002Fsync-obsidian-across-devices",{"path":65},"\u002Fen\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":67},"\u002Fen\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":69},"\u002Fen\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":71},"\u002Fen\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":73},"\u002Fes\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":75},"\u002Fes\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":77},"\u002Fes\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":79},"\u002Fes\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":81},"\u002Fes\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":83},"\u002Fes\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":85},"\u002Fes\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":87},"\u002Fes\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":89},"\u002Fes\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":91},"\u002Fes\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":93},"\u002Fes\u002Farticle\u002Fsetup-antigravity-2",{"path":95},"\u002Fes\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":97},"\u002Fes\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":99},"\u002Fes\u002Farticle\u002Fsync-obsidian-across-devices",{"path":101},"\u002Fes\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":103},"\u002Fes\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":105},"\u002Fes\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":107},"\u002Fes\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":109},"\u002Ffr\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":111},"\u002Ffr\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":113},"\u002Ffr\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":115},"\u002Ffr\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":117},"\u002Ffr\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":119},"\u002Ffr\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":121},"\u002Ffr\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":123},"\u002Ffr\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":125},"\u002Ffr\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":127},"\u002Ffr\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":129},"\u002Ffr\u002Farticle\u002Fsetup-antigravity-2",{"path":131},"\u002Ffr\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":133},"\u002Ffr\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":135},"\u002Ffr\u002Farticle\u002Fsync-obsidian-across-devices",{"path":137},"\u002Ffr\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":139},"\u002Ffr\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":141},"\u002Ffr\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":143},"\u002Ffr\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":145},"\u002Fid\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":147},"\u002Fid\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":149},"\u002Fid\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":151},"\u002Fid\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":153},"\u002Fid\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":155},"\u002Fid\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":157},"\u002Fid\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":159},"\u002Fid\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":161},"\u002Fid\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":163},"\u002Fid\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":165},"\u002Fid\u002Farticle\u002Fsetup-antigravity-2",{"path":167},"\u002Fid\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":169},"\u002Fid\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":171},"\u002Fid\u002Farticle\u002Fsync-obsidian-across-devices",{"path":173},"\u002Fid\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":175},"\u002Fid\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":177},"\u002Fid\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":179},"\u002Fid\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":181},"\u002Fja\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":183},"\u002Fja\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":185},"\u002Fja\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":187},"\u002Fja\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":189},"\u002Fja\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":191},"\u002Fja\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":193},"\u002Fja\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":195},"\u002Fja\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":197},"\u002Fja\u002Farticle\u002Fsetup-antigravity-2",{"path":199},"\u002Fja\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":201},"\u002Fja\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":203},"\u002Fja\u002Farticle\u002Fsync-obsidian-across-devices",{"path":205},"\u002Fja\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":207},"\u002Fja\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":209},"\u002Fja\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":211},"\u002Fja\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":213},"\u002Fpt\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":215},"\u002Fpt\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":217},"\u002Fpt\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":219},"\u002Fpt\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":221},"\u002Fpt\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":223},"\u002Fpt\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":225},"\u002Fpt\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":227},"\u002Fpt\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":229},"\u002Fpt\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":231},"\u002Fpt\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":233},"\u002Fpt\u002Farticle\u002Fsetup-antigravity-2",{"path":235},"\u002Fpt\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":237},"\u002Fpt\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":239},"\u002Fpt\u002Farticle\u002Fsync-obsidian-across-devices",{"path":241},"\u002Fpt\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":243},"\u002Fpt\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":245},"\u002Fpt\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":247},"\u002Fpt\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":249},"\u002Ftw\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":251},"\u002Ftw\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":253},"\u002Ftw\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":255},"\u002Ftw\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":257},"\u002Ftw\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":259},"\u002Ftw\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":261},"\u002Ftw\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":263},"\u002Ftw\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":265},"\u002Ftw\u002Farticle\u002Fsetup-antigravity-2",{"path":267},"\u002Ftw\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":269},"\u002Ftw\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":271},"\u002Ftw\u002Farticle\u002Fsync-obsidian-across-devices",{"path":273},"\u002Ftw\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":275},"\u002Ftw\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":277},"\u002Ftw\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":279},"\u002Ftw\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":281},"\u002Fvi\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":283},"\u002Fvi\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":285},"\u002Fvi\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":287},"\u002Fvi\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":289},"\u002Fvi\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":291},"\u002Fvi\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"path":293},"\u002Fvi\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":295},"\u002Fvi\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":297},"\u002Fvi\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":299},"\u002Fvi\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"path":301},"\u002Fvi\u002Farticle\u002Fsetup-antigravity-2",{"path":303},"\u002Fvi\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":305},"\u002Fvi\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":307},"\u002Fvi\u002Farticle\u002Fsync-obsidian-across-devices",{"path":309},"\u002Fvi\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":311},"\u002Fvi\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":313},"\u002Fvi\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":315},"\u002Fvi\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"path":317},"\u002Fzh\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"path":319},"\u002Fzh\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"path":321},"\u002Fzh\u002Farticle\u002Fcentralised-the-skills-for-agents",{"path":323},"\u002Fzh\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"path":325},"\u002Fzh\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"path":327},"\u002Fzh\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"path":329},"\u002Fzh\u002Farticle\u002Fself-hosted-travel-planner-trek",{"path":331},"\u002Fzh\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"path":333},"\u002Fzh\u002Farticle\u002Fsetup-antigravity-2",{"path":335},"\u002Fzh\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"path":337},"\u002Fzh\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"path":339},"\u002Fzh\u002Farticle\u002Fsync-obsidian-across-devices",{"path":341},"\u002Fzh\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"path":343},"\u002Fzh\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"path":345},"\u002Fzh\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"path":347},"\u002Fzh\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",[349,353,357,361,365,369,373,377,381,385,389,393,397,401,405,409,413,417],{"title":350,"path":351,"stem":352},"AI Agent Skills: What They Are & How to Create Them","\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them","en\u002Farticle\u002Fai-agent-skills-what-they-are-how-to-create-them",{"title":354,"path":355,"stem":356},"Bringing Buzz to DeepSeek Harness: Taught to Speak Nostr","\u002Farticle\u002Fbringing-buzz-to-deepseek-harness","en\u002Farticle\u002Fbringing-buzz-to-deepseek-harness",{"title":358,"path":359,"stem":360},"Solving AI Agent Skills Fragmentation with npx skills","\u002Farticle\u002Fcentralised-the-skills-for-agents","en\u002Farticle\u002Fcentralised-the-skills-for-agents",{"title":362,"path":363,"stem":364},"How to Expose Hermes Agent Privately with Cloudflare WARP","\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp","en\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp",{"title":366,"path":367,"stem":368},"How AI Agent Skills Replace Nuxt App Scaffolding Scripts","\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts","en\u002Farticle\u002Fhow-ai-agent-skills-replace-nuxt-app-scaffolding-scripts",{"title":370,"path":371,"stem":372},"Stop Exposing Your Vault: Secure NodeWarden with Cloudflare","\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare","en\u002Farticle\u002Fhow-to-secure-nodewarden-at-cloudflare",{"title":374,"path":375,"stem":376},"How to Deploy Hermes Agent on a Linux VPS","\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server","en\u002Farticle\u002Fhow-to-setup-hermes-on-remote-server",{"title":378,"path":379,"stem":380},"Self-Host Your Travel Itineraries with TREK and Docker","\u002Farticle\u002Fself-hosted-travel-planner-trek","en\u002Farticle\u002Fself-hosted-travel-planner-trek",{"title":382,"path":383,"stem":384},"Self-Host Block's Buzz: Shared AI Agent Workspace","\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues","en\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues",{"title":386,"path":387,"stem":388},"How to Self-Host a BitWarden Compatible Server Nodewarden","\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare","en\u002Farticle\u002Fself-hosting-nodewarden-at-cloudflare",{"title":390,"path":391,"stem":392},"Google Antigravity 2 Hands-On: Setup & First Impressions","\u002Farticle\u002Fsetup-antigravity-2","en\u002Farticle\u002Fsetup-antigravity-2",{"title":394,"path":395,"stem":396},"NetSuite AI Connector Guide: MCP Setup & Use Cases","\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude","en\u002Farticle\u002Fsetup-netsuite-mcp-on-chatgpt-claude",{"title":398,"path":399,"stem":400},"Switch Between Multiple Cloudflare WARP Orgs on Mac","\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac","en\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac",{"title":402,"path":403,"stem":404},"How to Sync Obsidian Vaults Across Devices Securely","\u002Farticle\u002Fsync-obsidian-across-devices","en\u002Farticle\u002Fsync-obsidian-across-devices",{"title":406,"path":407,"stem":408},"Testing Claude Fable 5: A Financial Analysis Review","\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis","en\u002Farticle\u002Ftesting-claude-fable-5-in-financial-analysis",{"title":410,"path":411,"stem":412},"Guide to Browser and Scheduler in Antigravity 2","\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2","en\u002Farticle\u002Fuse-browser-and-scheduler-in-antigravity-2",{"title":414,"path":415,"stem":416},"Build a Persistent AI Memory System on Cloudflare","\u002Farticle\u002Fuse-cloudflare-as-ai-memory","en\u002Farticle\u002Fuse-cloudflare-as-ai-memory",{"title":418,"path":419,"stem":420},"Antigravity 2 in Action: AI Agents, Skills, and MCP","\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2","en\u002Farticle\u002Fwhat-can-we-do-with-antigravity-2",{"id":422,"title":402,"author":423,"body":424,"category":1916,"date":1918,"description":1919,"extension":1920,"image":1921,"imageAlt":1922,"isPublished":737,"meta":1923,"minRead":1164,"navigation":737,"path":63,"seo":1932,"stem":404,"tags":1934,"updatedAt":1939,"__hash__":1940},"article\u002Fen\u002Farticle\u002Fsync-obsidian-across-devices.md","",{"type":425,"value":426,"toc":1894},"minimark",[427,431,437,448,457,477,482,490,495,500,516,532,535,540,545,552,557,561,566,641,649,681,685,693,701,708,775,778,797,804,816,820,824,835,840,846,850,871,876,890,895,900,905,920,923,928,931,936,940,945,959,963,977,988,992,997,1000,1010,1043,1047,1050,1202,1236,1242,1263,1274,1279,1283,1293,1366,1370,1376,1414,1545,1552,1558,1565,1571,1574,1580,1586,1600,1611,1618,1624,1631,1768,1774,1779,1782,1787,1790,1794,1799,1804,1810,1821,1831,1835,1846,1851,1857,1863,1867,1890],[428,429,430],"p",{},"Obsidian is a local-first knowledge management app. Every note is a markdown file on your device and remains entirely under your control. However, we often want the same vault across our laptop, phone, and other devices, or to be able to access it through a web browser remotely.",[432,433],"img",{"src":434,"alt":435,"style":436},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fobsidian-multi-device-sync-illustration.webp","Illustration of Obsidian vault synchronized across multiple devices","max-width: 667px; width: 100%; height: auto;",[428,438,439,440,447],{},"A number of synchronisation solutions are available for Obsidian, but they all make trade-offs regarding conflict handling, encryption, or data sovereignty. ",[441,442,446],"a",{"href":443,"rel":444},"https:\u002F\u002Fgithub.com\u002Fhjinco\u002Fsynch",[445],"nofollow","Synch"," is an open-source application that synchronises your Obsidian vault with end-to-end encryption and automatic conflict handling on a self-hosted server.",[428,449,450,451,456],{},"While Obsidian's local-first approach works perfectly most of the time, we may still need to access our vault through a web browser remotely on some occasions. ",[441,452,455],{"href":453,"rel":454},"https:\u002F\u002Fgithub.com\u002FNystik-gh\u002Fignis",[445],"Ignis"," is an open-source application that runs Obsidian inside a web browser in a close-to-native format, allowing you to read and edit your vault from anywhere.",[428,458,459,460,463,464,466,467,470,471,476],{},"In this guide, we will set up ",[461,462,446],"strong",{}," and ",[461,465,455],{}," on a ",[461,468,469],{},"VPS"," (Virtual Private Server), hosting them securely inside a ",[461,472,473],{},[441,474,475],{"href":363},"Cloudflare Zero Trust"," private network rather than exposing them to the open internet.",[432,478],{"src":479,"alt":480,"style":481},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fobsidian-sync-cloudflare-zero-trust-architecture.webp","Architecture diagram of Obsidian sync using Cloudflare Zero Trust","max-width: 671px; width: 100%; height: auto;",[483,484],"article-card",{"description":485,"image":486,"image-alt":487,"label":488,"min-read":489,"title":362,"to":363},"Learn how to securely expose and access your Hermes Agent globally using Cloudflare WARP and Zero Trust without opening inbound firewall ports.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002FEN-Exposing-Hermes-Agent-to-Private-Network-Using-Cloudflare-WARP.webp","Securely exposing Hermes Agent to a private network using Cloudflare Zero Trust and WARP tunnel","Related guide","8",[491,492,494],"h2",{"id":493},"secure-obsidian-vault-synchronisation-with-synch","Secure Obsidian Vault Synchronisation with Synch",[428,496,497,499],{},[461,498,446],{}," provides the following features:",[501,502,503,507,510,513],"ul",{},[504,505,506],"li",{},"Syncs your vault as soon as changes are detected",[504,508,509],{},"Encrypts vault data before upload",[504,511,512],{},"Allows restoration from version history",[504,514,515],{},"Includes automatic conflict handling",[428,517,518,520,521,524,525,528,529,531],{},[461,519,446],{}," generates a random 32-byte ",[461,522,523],{},"vault key"," on your device, which is used to encrypt your vault data. When you create a remote vault, you choose a ",[461,526,527],{},"vault password","; this password is used to protect the ",[461,530,523],{}," so that the key can be stored securely on the server and unlocked on other devices.",[428,533,534],{},"Note conflict resolution is handled on your client devices rather than on the server. If two devices edit the same note simultaneously, the server keeps whichever version arrives first and flags the other device as out of date. The out-of-date device then automatically merges the newer version with its local changes before uploading the final merged note.",[536,537,539],"h3",{"id":538},"set-up-synch-on-your-vps","Set Up Synch on Your VPS",[541,542,544],"h4",{"id":543},"create-a-domain-name","Create a Domain Name",[428,546,547,548,551],{},"Create an A record in Cloudflare and set its proxy status to ",[461,549,550],{},"DNS only"," (bypassing the Cloudflare CDN).",[432,553],{"src":554,"alt":555,"style":556},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fcloudflare-dns-a-record-synch-server.webp","Configuring a DNS A record for the Synch server in Cloudflare","max-width: 538px; width: 100%; height: auto;",[541,558,560],{"id":559},"install-synch-docker-on-ubuntu","Install Synch Docker on Ubuntu",[562,563,565],"h5",{"id":564},"clone-the-repository","Clone the Repository",[567,568,572],"pre",{"className":569,"code":570,"language":571,"meta":423,"style":423},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","git clone https:\u002F\u002Fgithub.com\u002Fhjinco\u002Fsynch.git       \n        \n# Navigate to the API folder\ncd synch\u002Fapps\u002Fapi\n        \n# Copy the example environment file:\ncp .env.example .env\n","bash",[573,574,575,595,601,608,618,623,629],"code",{"__ignoreMap":423},[576,577,580,584,588,591],"span",{"class":578,"line":579},"line",1,[576,581,583],{"class":582},"sBMFI","git",[576,585,587],{"class":586},"sfazB"," clone",[576,589,590],{"class":586}," https:\u002F\u002Fgithub.com\u002Fhjinco\u002Fsynch.git",[576,592,594],{"class":593},"sTEyZ","       \n",[576,596,598],{"class":578,"line":597},2,[576,599,600],{"class":593},"        \n",[576,602,604],{"class":578,"line":603},3,[576,605,607],{"class":606},"sHwdD","# Navigate to the API folder\n",[576,609,611,615],{"class":578,"line":610},4,[576,612,614],{"class":613},"s2Zo4","cd",[576,616,617],{"class":586}," synch\u002Fapps\u002Fapi\n",[576,619,621],{"class":578,"line":620},5,[576,622,600],{"class":593},[576,624,626],{"class":578,"line":625},6,[576,627,628],{"class":606},"# Copy the example environment file:\n",[576,630,632,635,638],{"class":578,"line":631},7,[576,633,634],{"class":582},"cp",[576,636,637],{"class":586}," .env.example",[576,639,640],{"class":586}," .env\n",[562,642,644,645,648],{"id":643},"edit-env-values","Edit ",[573,646,647],{},".env"," Values",[501,650,651,657,675],{},[504,652,653,656],{},[573,654,655],{},"PUBLIC_URL=synch.pafor.me",": Enter the public domain name of your Synch server (the domain name created in the previous step).",[504,658,659,463,662,665,666,670,671,674],{},[573,660,661],{},"BETTER_AUTH_SECRET",[573,663,664],{},"SYNC_TOKEN_SECRET",": Generate secure keys using this ",[441,667,669],{"href":668},"\u002Ftools\u002Fsecret-key-hex","online secret-key tool"," or by running ",[573,672,673],{},"openssl rand -hex 32"," twice in your terminal.",[504,676,677,680],{},[573,678,679],{},"AUTH_ALLOWED_EMAILS",": A comma-separated list of the email addresses permitted to sign up and create accounts.",[562,682,684],{"id":683},"add-the-domain-to-caddyfile","Add the Domain to Caddyfile",[428,686,687,688,692],{},"The details of how the Cloudflare DNS module is integrated with Caddy and started within a container can be found in our ",[441,689,691],{"href":690},"\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues#_4-enable-https-with-caddy","self-hosting Buzz article",".",[483,694],{"description":695,"image":696,"image-alt":697,"label":698,"min-read":699,"title":700,"to":690},"Learn how to configure Caddy to automatically provision SSL\u002FTLS certificates using Cloudflare DNS challenges in Docker containers.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002FEN-Self-Hosting-Buzz-As-The-Workspace-Where-AI-Agents-Become-Colleagues.webp","Configuring Caddy with Cloudflare DNS API token for automated SSL\u002FTLS certificate generation in a self-hosted workspace","Self-hosting guide","12","How to Enable HTTPS with Caddy and Cloudflare DNS",[428,702,703,704,707],{},"Include the ",[573,705,706],{},"SYNCH_DOMAIN"," directive in your Caddyfile, pointing to port 8787 (the port used by the Synch container):",[567,709,713],{"className":710,"code":711,"language":712,"meta":423,"style":423},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}\n}\n\n{$SYNCH_DOMAIN} {\n  encode zstd gzip\n  reverse_proxy host.docker.internal:8787\n}\n","json",[573,714,715,721,729,733,739,753,758,770],{"__ignoreMap":423},[576,716,717],{"class":578,"line":579},[576,718,720],{"class":719},"sMK4o","{\n",[576,722,723,726],{"class":578,"line":597},[576,724,725],{"class":593},"  acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN",[576,727,728],{"class":719},"}\n",[576,730,731],{"class":578,"line":603},[576,732,728],{"class":593},[576,734,735],{"class":578,"line":610},[576,736,738],{"emptyLinePlaceholder":737},true,"\n",[576,740,741,744,747,750],{"class":578,"line":620},[576,742,743],{"class":719},"{",[576,745,746],{"class":593},"$SYNCH_DOMAIN",[576,748,749],{"class":719},"}",[576,751,752],{"class":719}," {\n",[576,754,755],{"class":578,"line":625},[576,756,757],{"class":593},"  encode zstd gzip\n",[576,759,760,763,766],{"class":578,"line":631},[576,761,762],{"class":593},"  reverse_proxy host.docker.internal",[576,764,765],{"class":719},":",[576,767,769],{"class":768},"sbssI","8787\n",[576,771,773],{"class":578,"line":772},8,[576,774,728],{"class":719},[428,776,777],{},"Start the container:",[567,779,781],{"className":569,"code":780,"language":571,"meta":423,"style":423},"docker compose up -d\n",[573,782,783],{"__ignoreMap":423},[576,784,785,788,791,794],{"class":578,"line":579},[576,786,787],{"class":582},"docker",[576,789,790],{"class":586}," compose",[576,792,793],{"class":586}," up",[576,795,796],{"class":586}," -d\n",[428,798,799,800,803],{},"Run the following ",[573,801,802],{},"curl"," command to check its availability:",[567,805,807],{"className":569,"code":806,"language":571,"meta":423,"style":423},"curl https:\u002F\u002Fsynch.pafor.me\u002Fhealth\n",[573,808,809],{"__ignoreMap":423},[576,810,811,813],{"class":578,"line":579},[576,812,802],{"class":582},[576,814,815],{"class":586}," https:\u002F\u002Fsynch.pafor.me\u002Fhealth\n",[536,817,819],{"id":818},"connecting-obsidian-to-your-synch-server","Connecting Obsidian to Your Synch Server",[541,821,823],{"id":822},"install-the-synch-plugin-on-obsidian","Install the Synch Plugin on Obsidian",[428,825,826,827,830,831,834],{},"Open Obsidian Settings, navigate to ",[461,828,829],{},"Community plugins",", and click the ",[461,832,833],{},"'Browse'"," button:",[432,836],{"src":837,"alt":838,"style":839},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fobsidian-community-plugins-browse.webp","Browsing community plugins in Obsidian settings","max-width: 523px; width: 100%; height: auto;",[428,841,842,843,765],{},"Search for and install ",[461,844,845],{},"'Synchrun'",[432,847],{"src":848,"alt":849,"style":556},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fobsidian-install-synchrun-plugin.webp","Installing the Synchrun plugin in Obsidian",[428,851,852,853,855,856,859,860,863,864,867,868,692],{},"Once ",[461,854,845],{}," is installed, open the plugin settings and enable ",[461,857,858],{},"'Use a self-hosted server'",". Then, enter ",[573,861,862],{},"https:\u002F\u002Fsynch.pafor.me"," in the ",[461,865,866],{},"'Server URL'"," field and click ",[461,869,870],{},"'Save'",[432,872],{"src":873,"alt":874,"style":875},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fobsidian-synchrun-plugin-settings-self-hosted.webp","Configuring self-hosted server URL in Synchrun plugin settings","max-width: 525px; width: 100%; height: auto;",[428,877,878,879,882,883,886,887,889],{},"Click the ",[461,880,881],{},"'Sign in on this device'"," button under ",[461,884,885],{},"'Account'",". Next, sign up for an account using the email address you specified in your ",[573,888,679],{}," list; you will then be redirected to the following authorization page:",[432,891],{"src":892,"alt":893,"style":894},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fsynchrun-account-authorization-page.webp","Account authorization page for Synchrun","max-width: 494px; width: 100%; height: auto;",[428,896,878,897,834],{},[461,898,899],{},"'Allow Obsidian sign-in'",[432,901],{"src":902,"alt":903,"style":904},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fsynchrun-allow-obsidian-signin.webp","Allowing Obsidian sign-in for Synch","max-width: 498px; width: 100%; height: auto;",[428,906,878,907,910,911,914,915],{},[461,908,909],{},"'Return to Obsidian'"," button, and then click ",[461,912,913],{},"'Create vault'",":\n",[432,916],{"src":917,"alt":918,"style":919},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fobsidian-synchrun-create-remote-vault.webp","Creating a new remote vault in Synchrun","max-width: 496px; width: 100%; height: auto;",[428,921,922],{},"Enter a name and secure password to create your remote vault.",[432,924],{"src":925,"alt":926,"style":927},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fobsidian-synchrun-vault-password-setup.webp","Setting up a secure password for the Obsidian remote vault","max-width: 500px; width: 100%; height: auto;",[428,929,930],{},"The synchronisation process will begin immediately and may take a while depending on the size of your vault. Once completed, your total storage usage will be displayed.",[432,932],{"src":933,"alt":934,"style":935},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fobsidian-synchrun-sync-completed-storage.webp","Synchrun sync completed showing total storage used","max-width: 508px; width: 100%; height: auto;",[491,937,939],{"id":938},"browser-based-obsidian-access-with-ignis","Browser-Based Obsidian Access with Ignis",[428,941,942,944],{},[461,943,455],{}," replaces Obsidian's Electron APIs with Web APIs, which allows Obsidian's JavaScript code to be executed directly in a standard web browser. All your markdown files and attachments are stored directly in the host server's file system.",[428,946,947,948,463,953,958],{},"However, there are a few limitations compared to the standalone Obsidian desktop application. Certain features or plugins that require Electron or Node.js APIs—which have no direct equivalent in a browser environment—will not work. Please refer to the Ignis ",[441,949,952],{"href":950,"rel":951},"https:\u002F\u002Fignis.thiefling.com\u002Fdocs\u002Fusing\u002Flimitations\u002F",[445],"Limitations",[441,954,957],{"href":955,"rel":956},"https:\u002F\u002Fignis.thiefling.com\u002Fdocs\u002Fusing\u002Fplugin-compatibility\u002F",[445],"Plugin compatibility"," guides for detailed compatibility listings.",[536,960,962],{"id":961},"ignis-setup","Ignis Setup",[428,964,965,966,968,969,972,973,976],{},"We will install ",[461,967,455],{}," on our VPS using Docker, mounting it to the local ",[573,970,971],{},".\u002Fvaults"," folder. This vault directory will be synchronised using the ",[461,974,975],{},"Synch CLI"," to pull note updates from the remote vault we set up earlier.",[428,978,979,980,982,983,987],{},"Since ",[461,981,455],{}," does not have built-in authentication, it must be secured behind a ",[461,984,985],{},[441,986,475],{"href":363}," private network.",[541,989,991],{"id":990},"create-dns-record","Create DNS Record",[432,993],{"src":994,"alt":995,"style":996},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fcloudflare-dns-a-record-ignis.webp","Configuring a DNS A record for the Ignis web client in Cloudflare","max-width: 552px; width: 100%; height: auto;",[541,998,684],{"id":999},"add-the-domain-to-caddyfile-1",[428,1001,1002,1003,1006,1007,765],{},"Add ",[573,1004,1005],{},"obsidian.pafor.me"," to your Caddyfile in the same way as ",[573,1008,1009],{},"synch.pafor.me",[567,1011,1013],{"className":710,"code":1012,"language":712,"meta":423,"style":423},"{$OBSIDIAN_DOMAIN} {\n  encode zstd gzip\n  reverse_proxy host.docker.internal:9898\n}\n",[573,1014,1015,1026,1030,1039],{"__ignoreMap":423},[576,1016,1017,1019,1022,1024],{"class":578,"line":579},[576,1018,743],{"class":719},[576,1020,1021],{"class":593},"$OBSIDIAN_DOMAIN",[576,1023,749],{"class":719},[576,1025,752],{"class":719},[576,1027,1028],{"class":578,"line":597},[576,1029,757],{"class":593},[576,1031,1032,1034,1036],{"class":578,"line":603},[576,1033,762],{"class":593},[576,1035,765],{"class":719},[576,1037,1038],{"class":768},"9898\n",[576,1040,1041],{"class":578,"line":610},[576,1042,728],{"class":719},[541,1044,1046],{"id":1045},"start-ignis-using-docker","Start Ignis using Docker",[428,1048,1049],{},"Save the following docker compose yml as ignis-docker-compose.yml on VPS:",[567,1051,1055],{"className":1052,"code":1053,"language":1054,"meta":423,"style":423},"language-yml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","services:\n  ignis:\n    image: nobbe\u002Fignis:latest\n    ports:\n      - \"9898:8080\"\n    environment:\n      # match these to your host user (run: id)\n      - PUID=1000\n      - PGID=1000\n      - WS_ORIGINS=https:\u002F\u002Fobsidian.pafor.me\n    volumes:\n      - .\u002Fvaults:\u002Fvaults\n      - .\u002Fdata:\u002Fapp\u002Fdata\n      - obsidian-app:\u002Fapp\u002Fobsidian-app\n    restart: unless-stopped\n\nvolumes:\n  obsidian-app:\n","yml",[573,1056,1057,1065,1072,1082,1089,1103,1110,1115,1122,1130,1138,1146,1154,1162,1170,1181,1186,1194],{"__ignoreMap":423},[576,1058,1059,1063],{"class":578,"line":579},[576,1060,1062],{"class":1061},"swJcz","services",[576,1064,914],{"class":719},[576,1066,1067,1070],{"class":578,"line":597},[576,1068,1069],{"class":1061},"  ignis",[576,1071,914],{"class":719},[576,1073,1074,1077,1079],{"class":578,"line":603},[576,1075,1076],{"class":1061},"    image",[576,1078,765],{"class":719},[576,1080,1081],{"class":586}," nobbe\u002Fignis:latest\n",[576,1083,1084,1087],{"class":578,"line":610},[576,1085,1086],{"class":1061},"    ports",[576,1088,914],{"class":719},[576,1090,1091,1094,1097,1100],{"class":578,"line":620},[576,1092,1093],{"class":719},"      -",[576,1095,1096],{"class":719}," \"",[576,1098,1099],{"class":586},"9898:8080",[576,1101,1102],{"class":719},"\"\n",[576,1104,1105,1108],{"class":578,"line":625},[576,1106,1107],{"class":1061},"    environment",[576,1109,914],{"class":719},[576,1111,1112],{"class":578,"line":631},[576,1113,1114],{"class":606},"      # match these to your host user (run: id)\n",[576,1116,1117,1119],{"class":578,"line":772},[576,1118,1093],{"class":719},[576,1120,1121],{"class":586}," PUID=1000\n",[576,1123,1125,1127],{"class":578,"line":1124},9,[576,1126,1093],{"class":719},[576,1128,1129],{"class":586}," PGID=1000\n",[576,1131,1133,1135],{"class":578,"line":1132},10,[576,1134,1093],{"class":719},[576,1136,1137],{"class":586}," WS_ORIGINS=https:\u002F\u002Fobsidian.pafor.me\n",[576,1139,1141,1144],{"class":578,"line":1140},11,[576,1142,1143],{"class":1061},"    volumes",[576,1145,914],{"class":719},[576,1147,1149,1151],{"class":578,"line":1148},12,[576,1150,1093],{"class":719},[576,1152,1153],{"class":586}," .\u002Fvaults:\u002Fvaults\n",[576,1155,1157,1159],{"class":578,"line":1156},13,[576,1158,1093],{"class":719},[576,1160,1161],{"class":586}," .\u002Fdata:\u002Fapp\u002Fdata\n",[576,1163,1165,1167],{"class":578,"line":1164},14,[576,1166,1093],{"class":719},[576,1168,1169],{"class":586}," obsidian-app:\u002Fapp\u002Fobsidian-app\n",[576,1171,1173,1176,1178],{"class":578,"line":1172},15,[576,1174,1175],{"class":1061},"    restart",[576,1177,765],{"class":719},[576,1179,1180],{"class":586}," unless-stopped\n",[576,1182,1184],{"class":578,"line":1183},16,[576,1185,738],{"emptyLinePlaceholder":737},[576,1187,1189,1192],{"class":578,"line":1188},17,[576,1190,1191],{"class":1061},"volumes",[576,1193,914],{"class":719},[576,1195,1197,1200],{"class":578,"line":1196},18,[576,1198,1199],{"class":1061},"  obsidian-app",[576,1201,914],{"class":719},[501,1203,1204,1215,1229],{},[504,1205,1206,1207,1210,1211,1214],{},"Use port ",[573,1208,1209],{},"9898"," on the host, as ",[573,1212,1213],{},"8080"," is commonly used by other services.",[504,1216,1217,1218,1221,1222,463,1225,1228],{},"Run the ",[573,1219,1220],{},"id"," command on your VPS to verify your host user's ",[573,1223,1224],{},"UID",[573,1226,1227],{},"GID"," to ensure correct file system permissions.",[504,1230,1231,1232,1235],{},"Set ",[573,1233,1234],{},"WS_ORIGINS"," to only allow WebSocket connections originating from your specific domain name.",[428,1237,1238,1239,1241],{},"Start the ",[461,1240,455],{}," docker:",[567,1243,1245],{"className":569,"code":1244,"language":571,"meta":423,"style":423},"docker compose -f ignis-docker-compose.yml up -d\n",[573,1246,1247],{"__ignoreMap":423},[576,1248,1249,1251,1253,1256,1259,1261],{"class":578,"line":579},[576,1250,787],{"class":582},[576,1252,790],{"class":586},[576,1254,1255],{"class":586}," -f",[576,1257,1258],{"class":586}," ignis-docker-compose.yml",[576,1260,793],{"class":586},[576,1262,796],{"class":586},[428,1264,1265,1266,1269,1270,1273],{},"When you navigate to your domain in a web browser, the ",[461,1267,1268],{},"'Vault Manager'"," will appear. It will be empty as no vaults are configured yet. We will set up the ",[461,1271,1272],{},"'Synch CLI'"," in the next section to synchronise contents from our remote vault.",[432,1275],{"src":1276,"alt":1277,"style":1278},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fignis-vault-manager-empty.webp","Empty Vault Manager interface in Ignis web client","max-width: 466px; width: 100%; height: auto;",[541,1280,1282],{"id":1281},"firewall-issue","Firewall Issue",[428,1284,1285,1286,1289,1290,765],{},"By default, Docker automatically inserts its own DNAT and FORWARD rules, which route public traffic directly to active containers. This bypasses the standard Ubuntu UFW\u002Fiptables ",[573,1287,1288],{},"INPUT"," chain. To block external public traffic and keep the containers private, manually add the following rules to ",[573,1291,1292],{},"iptables",[567,1294,1296],{"className":569,"code":1295,"language":571,"meta":423,"style":423},"# Block all external public traffic\nsudo iptables -I DOCKER-USER -i ext_if -j DROP \n\n# Allow traffic only from your Cloudflare WARP client private IP\nsudo iptables -I DOCKER-USER -i ext_if -s 100.96.0.10 -j ACCEPT\n",[573,1297,1298,1303,1332,1336,1341],{"__ignoreMap":423},[576,1299,1300],{"class":578,"line":579},[576,1301,1302],{"class":606},"# Block all external public traffic\n",[576,1304,1305,1308,1311,1314,1317,1320,1323,1326,1329],{"class":578,"line":597},[576,1306,1307],{"class":582},"sudo",[576,1309,1310],{"class":586}," iptables",[576,1312,1313],{"class":586}," -I",[576,1315,1316],{"class":586}," DOCKER-USER",[576,1318,1319],{"class":586}," -i",[576,1321,1322],{"class":586}," ext_if",[576,1324,1325],{"class":586}," -j",[576,1327,1328],{"class":586}," DROP",[576,1330,1331],{"class":593}," \n",[576,1333,1334],{"class":578,"line":603},[576,1335,738],{"emptyLinePlaceholder":737},[576,1337,1338],{"class":578,"line":610},[576,1339,1340],{"class":606},"# Allow traffic only from your Cloudflare WARP client private IP\n",[576,1342,1343,1345,1347,1349,1351,1353,1355,1358,1361,1363],{"class":578,"line":620},[576,1344,1307],{"class":582},[576,1346,1310],{"class":586},[576,1348,1313],{"class":586},[576,1350,1316],{"class":586},[576,1352,1319],{"class":586},[576,1354,1322],{"class":586},[576,1356,1357],{"class":586}," -s",[576,1359,1360],{"class":768}," 100.96.0.10",[576,1362,1325],{"class":586},[576,1364,1365],{"class":586}," ACCEPT\n",[541,1367,1369],{"id":1368},"synch-cli-configuration","Synch CLI Configuration",[428,1371,1372,1373,1375],{},"The ",[461,1374,975],{}," is a headless tool that allows an Obsidian vault directory to be synchronised directly on remote servers without requiring the full desktop application to be installed.",[428,1377,1378,1379,1381,1382,1385,1386,1389,1390,1393,1394,1397,1398,1401,1402,1405,1406,1409,1410,1413],{},"Build the ",[461,1380,975],{}," from your cloned ",[573,1383,1384],{},"synch"," repository. Building requires ",[461,1387,1388],{},"Node.js >= 22.5"," (as the CLI depends on ",[573,1391,1392],{},"node:sqlite"," and global browser APIs such as ",[573,1395,1396],{},"fetch",", ",[573,1399,1400],{},"WebSocket",", and ",[573,1403,1404],{},"WebCrypto",") and ",[461,1407,1408],{},"pnpm"," (since the repository is structured as a pnpm workspace using version ",[573,1411,1412],{},"10.33.0","):",[567,1415,1417],{"className":569,"code":1416,"language":571,"meta":423,"style":423},"# Check versions\nnode --version   # must be >= 22.5\npnpm --version\n\n# In the repos root\npnpm install\n\n# Build the CLI bundle\npnpm -C apps\u002Fcli build\n\n# After a successful build you have `apps\u002Fcli\u002Fdist\u002Fsynch.js`. Make it executable and put it on your PATH\nchmod +x apps\u002Fcli\u002Fdist\u002Fsynch.js\nln -sf \"$PWD\u002Fapps\u002Fcli\u002Fdist\u002Fsynch.js\" \"$HOME\u002F.local\u002Fbin\u002Fsynch\"\n\n# Verification\nsynch --help\n",[573,1418,1419,1424,1435,1442,1446,1451,1458,1462,1467,1480,1484,1489,1500,1529,1533,1538],{"__ignoreMap":423},[576,1420,1421],{"class":578,"line":579},[576,1422,1423],{"class":606},"# Check versions\n",[576,1425,1426,1429,1432],{"class":578,"line":597},[576,1427,1428],{"class":582},"node",[576,1430,1431],{"class":586}," --version",[576,1433,1434],{"class":606},"   # must be >= 22.5\n",[576,1436,1437,1439],{"class":578,"line":603},[576,1438,1408],{"class":582},[576,1440,1441],{"class":586}," --version\n",[576,1443,1444],{"class":578,"line":610},[576,1445,738],{"emptyLinePlaceholder":737},[576,1447,1448],{"class":578,"line":620},[576,1449,1450],{"class":606},"# In the repos root\n",[576,1452,1453,1455],{"class":578,"line":625},[576,1454,1408],{"class":582},[576,1456,1457],{"class":586}," install\n",[576,1459,1460],{"class":578,"line":631},[576,1461,738],{"emptyLinePlaceholder":737},[576,1463,1464],{"class":578,"line":772},[576,1465,1466],{"class":606},"# Build the CLI bundle\n",[576,1468,1469,1471,1474,1477],{"class":578,"line":1124},[576,1470,1408],{"class":582},[576,1472,1473],{"class":586}," -C",[576,1475,1476],{"class":586}," apps\u002Fcli",[576,1478,1479],{"class":586}," build\n",[576,1481,1482],{"class":578,"line":1132},[576,1483,738],{"emptyLinePlaceholder":737},[576,1485,1486],{"class":578,"line":1140},[576,1487,1488],{"class":606},"# After a successful build you have `apps\u002Fcli\u002Fdist\u002Fsynch.js`. Make it executable and put it on your PATH\n",[576,1490,1491,1494,1497],{"class":578,"line":1148},[576,1492,1493],{"class":582},"chmod",[576,1495,1496],{"class":586}," +x",[576,1498,1499],{"class":586}," apps\u002Fcli\u002Fdist\u002Fsynch.js\n",[576,1501,1502,1505,1508,1510,1513,1516,1519,1521,1524,1527],{"class":578,"line":1156},[576,1503,1504],{"class":582},"ln",[576,1506,1507],{"class":586}," -sf",[576,1509,1096],{"class":719},[576,1511,1512],{"class":593},"$PWD",[576,1514,1515],{"class":586},"\u002Fapps\u002Fcli\u002Fdist\u002Fsynch.js",[576,1517,1518],{"class":719},"\"",[576,1520,1096],{"class":719},[576,1522,1523],{"class":593},"$HOME",[576,1525,1526],{"class":586},"\u002F.local\u002Fbin\u002Fsynch",[576,1528,1102],{"class":719},[576,1530,1531],{"class":578,"line":1164},[576,1532,738],{"emptyLinePlaceholder":737},[576,1534,1535],{"class":578,"line":1172},[576,1536,1537],{"class":606},"# Verification\n",[576,1539,1540,1542],{"class":578,"line":1183},[576,1541,1384],{"class":582},[576,1543,1544],{"class":586}," --help\n",[428,1546,1547,1548,1551],{},"Since the Synch CLI is running on the same VPS as your Synch remote vault, it can connect to the local API server directly. If you are configuring a different server, run ",[573,1549,1550],{},"synch login --api-url \u003Cremote-synch-api-url>"," to define your target API endpoint.",[428,1553,1554],{},[432,1555],{"alt":1556,"src":1557},"Running synch login with custom API URL in terminal","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fsynch-login-api-url-terminal.webp",[428,1559,1560,1561,1564],{},"Run ",[573,1562,1563],{},"synch login"," in your terminal, and you will receive an authentication URL:",[428,1566,1567],{},[432,1568],{"alt":1569,"src":1570},"Terminal output showing the authentication URL for Synch CLI","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fsynch-login-auth-url-terminal.webp",[428,1572,1573],{},"Log in via the web page using the same email address registered with your Obsidian desktop Synchrun plugin.",[428,1575,1576],{},[432,1577],{"alt":1578,"src":1579},"Successful web login for Synch CLI authorization","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fsynch-web-login-success.webp",[428,1581,1560,1582,1585],{},[573,1583,1584],{},"synch vault connect --vault ~\u002Fvaults\u002F\u003Cvaultname> --vault-id asadqe-7b29-4677-fsad-234asdafasd"," to link your local vault directory on the VPS to the remote vault.",[428,1587,1588,1589,1592,1593,1596,1597,1413],{},"The remote vault ID can be found inside the ",[461,1590,1591],{},"Synchrun"," plugin settings by clicking ",[461,1594,1595],{},"'Manage remote vaults'",". This will display a web page showing a list of your remote vaults, each identified by a unique GUID (e.g., ",[573,1598,1599],{},"123e4567-e89b-12d3-a456-426614174000",[428,1601,1602,1607],{},[432,1603],{"src":1604,"alt":1605,"style":1606},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fsynchrun-manage-remote-vaults.webp","Managing remote vaults in the Synchrun plugin","max-width: 582px; width: 100%; height: auto;",[432,1608],{"alt":1609,"src":1610},"Locating the unique remote vault ID in Synchrun","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fsynchrun-remote-vault-id.webp",[428,1612,1613,1614,1617],{},"Enter your vault password when prompted to establish the link. Once connected, run ",[573,1615,1616],{},"synch sync --vault ~\u002Fvaults\u002F\u003Cvault-name>"," to perform your initial synchronisation. This first run may take some time depending on your vault size.",[428,1619,1620],{},[432,1621],{"alt":1622,"src":1623},"Initial vault synchronization progress in Synch CLI","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fsynch-cli-initial-sync-progress.webp",[428,1625,1626,1627,1630],{},"To automate this, set up and enable a systemd service to run ",[573,1628,1629],{},"synch watch"," continuously, ensuring changes are synchronised instantly on boot:",[567,1632,1634],{"className":569,"code":1633,"language":571,"meta":423,"style":423},"sudo tee \u002Fetc\u002Fsystemd\u002Fsystem\u002Fsynch-watch.service \u003C\u003C'EOF'\n[Unit]\nDescription=Synch vault watcher\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nUser=\u003Cusername>\nExecStart=\u002Fhome\u002F\u003Cusername>\u002F.local\u002Fbin\u002Fsynch watch --vault \u002Fhome\u002F\u003Cusername>\u002Fvaults\u002F\u003Cvault-name>\nWorkingDirectory=\u002Fhome\u002F\u003Cusername>\u002Fvaults\nEnvironment=\"PATH=\u002Fhome\u002F\u003Cusername>\u002F.local\u002Fbin:\u002Fhome\u002F\u003Cusername>\u002F.cargo\u002Fbin:\u002Fusr\u002Flocal\u002Fsbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fsbin:\u002Fusr\u002Fbin:\u002Fsbin:\u002Fbin\"\nEnvironment=\"HOME=\u002Fhome\u002F\u003Cusername>\"\nRestart=always\nRestartSec=5\n\n[Install]\nWantedBy=multi-user.target\nEOF\nsudo systemctl daemon-reload\nsudo systemctl enable --now synch-watch.service\n",[573,1635,1636,1652,1657,1662,1667,1672,1676,1681,1686,1691,1696,1701,1706,1711,1716,1721,1725,1730,1735,1741,1752],{"__ignoreMap":423},[576,1637,1638,1640,1643,1646,1649],{"class":578,"line":579},[576,1639,1307],{"class":582},[576,1641,1642],{"class":586}," tee",[576,1644,1645],{"class":586}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fsynch-watch.service",[576,1647,1648],{"class":719}," \u003C\u003C",[576,1650,1651],{"class":719},"'EOF'\n",[576,1653,1654],{"class":578,"line":597},[576,1655,1656],{"class":586},"[Unit]\n",[576,1658,1659],{"class":578,"line":603},[576,1660,1661],{"class":586},"Description=Synch vault watcher\n",[576,1663,1664],{"class":578,"line":610},[576,1665,1666],{"class":586},"After=network-online.target\n",[576,1668,1669],{"class":578,"line":620},[576,1670,1671],{"class":586},"Wants=network-online.target\n",[576,1673,1674],{"class":578,"line":625},[576,1675,738],{"emptyLinePlaceholder":737},[576,1677,1678],{"class":578,"line":631},[576,1679,1680],{"class":586},"[Service]\n",[576,1682,1683],{"class":578,"line":772},[576,1684,1685],{"class":586},"Type=simple\n",[576,1687,1688],{"class":578,"line":1124},[576,1689,1690],{"class":586},"User=\u003Cusername>\n",[576,1692,1693],{"class":578,"line":1132},[576,1694,1695],{"class":586},"ExecStart=\u002Fhome\u002F\u003Cusername>\u002F.local\u002Fbin\u002Fsynch watch --vault \u002Fhome\u002F\u003Cusername>\u002Fvaults\u002F\u003Cvault-name>\n",[576,1697,1698],{"class":578,"line":1140},[576,1699,1700],{"class":586},"WorkingDirectory=\u002Fhome\u002F\u003Cusername>\u002Fvaults\n",[576,1702,1703],{"class":578,"line":1148},[576,1704,1705],{"class":586},"Environment=\"PATH=\u002Fhome\u002F\u003Cusername>\u002F.local\u002Fbin:\u002Fhome\u002F\u003Cusername>\u002F.cargo\u002Fbin:\u002Fusr\u002Flocal\u002Fsbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fsbin:\u002Fusr\u002Fbin:\u002Fsbin:\u002Fbin\"\n",[576,1707,1708],{"class":578,"line":1156},[576,1709,1710],{"class":586},"Environment=\"HOME=\u002Fhome\u002F\u003Cusername>\"\n",[576,1712,1713],{"class":578,"line":1164},[576,1714,1715],{"class":586},"Restart=always\n",[576,1717,1718],{"class":578,"line":1172},[576,1719,1720],{"class":586},"RestartSec=5\n",[576,1722,1723],{"class":578,"line":1183},[576,1724,738],{"emptyLinePlaceholder":737},[576,1726,1727],{"class":578,"line":1188},[576,1728,1729],{"class":586},"[Install]\n",[576,1731,1732],{"class":578,"line":1196},[576,1733,1734],{"class":586},"WantedBy=multi-user.target\n",[576,1736,1738],{"class":578,"line":1737},19,[576,1739,1740],{"class":719},"EOF\n",[576,1742,1744,1746,1749],{"class":578,"line":1743},20,[576,1745,1307],{"class":582},[576,1747,1748],{"class":586}," systemctl",[576,1750,1751],{"class":586}," daemon-reload\n",[576,1753,1755,1757,1759,1762,1765],{"class":578,"line":1754},21,[576,1756,1307],{"class":582},[576,1758,1748],{"class":586},[576,1760,1761],{"class":586}," enable",[576,1763,1764],{"class":586}," --now",[576,1766,1767],{"class":586}," synch-watch.service\n",[428,1769,1770,1771,1773],{},"Open ",[573,1772,1005],{}," in your web browser. You will find that the user interface and layout are virtually identical to the desktop app:",[432,1775],{"src":1776,"alt":1777,"style":1778},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fignis-web-interface-desktop-view.webp","Ignis web interface displaying the Obsidian vault on desktop","max-width: 593px; width: 100%; height: auto;",[428,1780,1781],{},"Clicking the settings icon reveals that almost all core configurations are intact, though your community plugins will need to be reinstalled:",[432,1783],{"src":1784,"alt":1785,"style":1786},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fignis-settings-community-plugins.webp","Community plugins settings in the Ignis web interface","max-width: 597px; width: 100%; height: auto;",[428,1788,1789],{},"To test the setup, you can add a new note via the web interface:",[432,1791],{"src":1792,"alt":1793,"style":1786},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fignis-create-new-note-web.webp","Creating a new markdown note via the Ignis web interface",[428,1795,1796,1797,692],{},"The note is immediately synchronised back to your Obsidian desktop app. Note that empty folders do not appear in ",[461,1798,455],{},[432,1800],{"src":1801,"alt":1802,"style":1803},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fobsidian-desktop-synced-note.webp","Newly created note successfully synced to the Obsidian desktop app","max-width: 502px; width: 100%; height: auto;",[428,1805,1806,1807,1809],{},"Viewing ",[573,1808,1005],{}," on a mobile web browser:",[428,1811,1812,1817],{},[432,1813],{"src":1814,"alt":1815,"style":1816},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fignis-mobile-view-sidebar.webp","Sidebar navigation of the Ignis web client on a mobile device","max-width: 269px; width: 100%; height: auto;",[432,1818],{"src":1819,"alt":1820,"style":1816},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002Fignis-mobile-view-editor.webp","Markdown note editor of the Ignis web client on a mobile device",[428,1822,1823,1824,1826,1827,1830],{},"When you delete a note on ",[461,1825,455],{},", it is safely moved to your local vault's ",[573,1828,1829],{},"~\u002Fvaults\u002F\u003Cvault-name>\u002F.trash"," folder.",[491,1832,1834],{"id":1833},"final-thoughts-on-self-hosted-vaults","Final Thoughts on Self-Hosted Vaults",[428,1836,1837,1838,463,1840,1842,1843,1845],{},"Together, ",[461,1839,446],{},[461,1841,455],{}," make your primary Obsidian vault seamlessly available across all of your devices, completely hosted on infrastructure under your direct control. Positioning these services inside a ",[461,1844,475],{}," private network ensures that your personal notes are entirely shielded from the public internet.",[428,1847,1848,1850],{},[461,1849,455],{}," is not intended to fully replace the native Obsidian desktop app. Instead, it serves as a lightweight, temporary web client for accessing and editing your vault when you are away from your main computer. For day-to-day writing and extensive vault management, the native Obsidian application remains the most comfortable choice.",[428,1852,1853,1854,1856],{},"Because Synch uses end-to-end encryption, your remote vault password must be highly secure to protect against brute-force guessing attacks. It is critical that you never lose this password—the server does not store the unencrypted ",[461,1855,523],{},", and if forgotten, your data will be completely unrecoverable. Additionally, ensure that your VPS instance, alongside any automated snapshots or backups, is properly secured and maintained.",[428,1858,1859,1860,1862],{},"While ",[461,1861,446],{},"'s encrypted version history and deleted-file recovery tools cover most accidental losses, keeping a separate, independent backup of your Obsidian vault is still highly recommended.",[491,1864,1866],{"id":1865},"references","References",[501,1868,1869,1876,1883],{},[504,1870,1871],{},[441,1872,1875],{"href":1873,"rel":1874},"https:\u002F\u002Fsynch.run\u002Fself-hosting-docker\u002F",[445],"Synch Deploy with Docker Compose",[504,1877,1878],{},[441,1879,1882],{"href":1880,"rel":1881},"https:\u002F\u002Fignis.thiefling.com\u002Fdocs\u002Fserver\u002Fdeploy\u002F",[445],"Ignis Deploy with Docker",[504,1884,1885],{},[441,1886,1889],{"href":1887,"rel":1888},"https:\u002F\u002Fsynch.run\u002Fblog\u002Fencryption-and-decryption\u002F",[445],"How does end-to-end encryption work in Synch?",[1891,1892,1893],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":423,"searchDepth":597,"depth":603,"links":1895},[1896,1905,1914,1915],{"id":493,"depth":597,"text":494,"children":1897},[1898,1902],{"id":538,"depth":603,"text":539,"children":1899},[1900,1901],{"id":543,"depth":610,"text":544},{"id":559,"depth":610,"text":560},{"id":818,"depth":603,"text":819,"children":1903},[1904],{"id":822,"depth":610,"text":823},{"id":938,"depth":597,"text":939,"children":1906},[1907],{"id":961,"depth":603,"text":962,"children":1908},[1909,1910,1911,1912,1913],{"id":990,"depth":610,"text":991},{"id":999,"depth":610,"text":684},{"id":1045,"depth":610,"text":1046},{"id":1281,"depth":610,"text":1282},{"id":1368,"depth":610,"text":1369},{"id":1833,"depth":597,"text":1834},{"id":1865,"depth":597,"text":1866},[1917],"productivity","2026-09-15","Securely synchronise Obsidian vaults across your devices and access notes on the web using self-hosted Synch and Ignis within Cloudflare Zero Trust.","md","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSync%20Obsidian%20Across%20Devices\u002FEN-Sync-Obsidian-Across-Devices.webp","Securely synchronising Obsidian vaults across multiple devices using self-hosted Synch and Ignis web client inside Cloudflare Zero Trust",{"schemaOrg":1924,"robots":1929,"sitemap":1930},[1925,1927],{"@type":1926,"headline":402,"description":1919,"image":1921},"Article",{"@type":1928,"name":402,"description":1919,"image":1921},"HowTo","index, follow",{"lastmod":1931},"2026-09-16",{"title":1933,"description":1919,"ogTitle":402,"ogDescription":1919,"twitterTitle":402,"twitterDescription":1919},"Secure Self-Hosted Obsidian Sync with Synch & Ignis",[1935,1936,1937,1938],"Self-hosting","Obsidian","Sync","Zero Trust",null,"NmSkE1ri49cYPhoFTZtGO8tViPA-_S4FK-pDGfoT1H4",{"surround":1942,"related":5045},[1943,4132],{"id":1944,"title":382,"author":423,"body":1945,"category":4094,"date":4097,"description":4098,"extension":1920,"image":696,"imageAlt":4099,"isPublished":737,"meta":4100,"minRead":1183,"navigation":737,"path":383,"seo":4124,"stem":384,"tags":4126,"updatedAt":1939,"__hash__":4131},"article\u002Fen\u002Farticle\u002Fself-hosting-buzz-as-the-workspace-where-ai-agents-become-colleagues.md",{"type":425,"value":1946,"toc":4064},[1947,1950,1956,1962,1966,1969,2007,2011,2017,2055,2059,2063,2077,2083,2085,2089,2093,2109,2115,2165,2191,2195,2202,2208,2212,2215,2425,2429,2469,2474,2481,2489,2538,2544,2570,2574,2578,2605,2631,2636,2678,2687,2959,2963,3006,3011,3018,3022,3026,3050,3053,3059,3062,3066,3074,3080,3083,3089,3095,3124,3130,3136,3139,3145,3149,3152,3155,3158,3164,3167,3173,3179,3185,3190,3194,3205,3212,3218,3221,3227,3231,3238,3244,3251,3255,3263,3327,3340,3395,3398,3469,3475,3491,3497,3501,3547,3553,3556,3562,3565,3571,3575,3591,3607,3613,3711,3714,3720,3731,3780,3786,3792,3804,3820,3823,3829,3833,3842,3864,3874,3972,3983,3989,3996,4002,4005,4011,4014,4020,4024,4027,4031,4061],[428,1948,1949],{},"Context fragmentation is a frustrating hurdle when working with multiple AI agents. With conversations scattered across different tools, you end up acting as a human router by copying conversations from Claude Code to paste into Gemini CLI, then copying from Gemini CLI to paste into Hermes Agent. This friction increases when human colleagues are on the same team.",[428,1951,1952],{},[432,1953],{"alt":1954,"src":1955},"The user interface of the Buzz collaborative workspace showing chat channels and active AI agents","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-workspace-interface.webp",[428,1957,1958,1961],{},[461,1959,1960],{},"Buzz",", an open-source collaboration workspace, brings human teams and AI agents together into a single, unified environment. Here, human colleagues and AI agents share the same task and project history, seamlessly handing work off to one another.",[491,1963,1965],{"id":1964},"what-is-blocks-buzz-the-collaborative-ai-agent-workspace","What is Block's Buzz? The Collaborative AI Agent Workspace",[428,1967,1968],{},"Buzz is an open-source collaboration workspace from Block (Jack Dorsey's company) where humans and AI agents share the same channels and projects. It offers the following key features:",[501,1970,1971,1977,1983,1989,1995,2001],{},[504,1972,1973,1976],{},[461,1974,1975],{},"Shared context:"," Channels are where humans and agents collaborate with one another. All conversational and project history is contained within the channel.",[504,1978,1979,1982],{},[461,1980,1981],{},"Agent-to-agent communication:"," Agents can communicate with each other, even across different machines. An agent can @-mention another agent to hand off work or cross-check code.",[504,1984,1985,1988],{},[461,1986,1987],{},"Mention-driven activation:"," Agents only act when @-mentioned, otherwise staying quiet. When mentioned, an agent reads the relevant context in the channel and start working.",[504,1990,1991,1994],{},[461,1992,1993],{},"Unified identity system:"," Humans and agents use the same identity system, authenticated via cryptographic keys.",[504,1996,1997,2000],{},[461,1998,1999],{},"Delegated commands:"," You can grant human colleagues permission to command your agents, allowing the entire team to brief and leverage each other's digital helpers.",[504,2002,2003,2006],{},[461,2004,2005],{},"Self-hosted servers:"," Because you host the server, your data remains fully under your control. You choose who joins and define your own operational rules.",[491,2008,2010],{"id":2009},"the-cryptographic-nostr-powered-architecture-of-buzz","The Cryptographic, Nostr-Powered Architecture of Buzz",[428,2012,2013],{},[432,2014],{"alt":2015,"src":2016},"Cryptographic, Nostr-powered architectural diagram of the Buzz collaboration workspace","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-nostr-cryptographic-architecture.webp",[501,2018,2019,2025,2031,2037,2043,2049],{},[504,2020,2021,2024],{},[461,2022,2023],{},"The Nostr relay acts as the server:"," Messages, workflows, repositories, and other events are cryptographically signed, verified, and stored on a Nostr relay server. The Nostr protocol natively supports communication over WebSockets and REST APIs.",[504,2026,2027,2030],{},[461,2028,2029],{},"Unified cryptographic identity:"," Both humans and agents authenticate using their own cryptographic keys. This identity remains client-side and is never stored on the server.",[504,2032,2033,2036],{},[461,2034,2035],{},"First-class agent membership:"," Every agent possesses its own identity, channel memberships, and audit trail. Agents connect to the workspace using the Agent Communication Protocol (ACP).",[504,2038,2039,2042],{},[461,2040,2041],{},"Decentralised Git repositories:"," Code repositories are stored on S3 compatible object storage, while tasks, pull requests, and code reviews are tracked within the Nostr event log. Consequently, a Buzz Git repository is hosted on the Nostr relay rather than GitHub.",[504,2044,2045,2048],{},[461,2046,2047],{},"The Buzz app is a Nostr client:"," Buzz is separate from the Nostr relay; it is a desktop\u002Fmobile client application that connects to the relay's URL.",[504,2050,2051,2054],{},[461,2052,2053],{},"Infrastructure stack:"," A PostgreSQL database handles event storage and full-text search, Redis manages pub\u002Fsub messaging, and S3 compatible MinIO is used for media storage.",[491,2056,2058],{"id":2057},"how-to-self-host-blocks-buzz-relay-on-a-linux-vps","How to Self-Host Block's Buzz Relay on a Linux VPS",[536,2060,2062],{"id":2061},"_0-prerequisites","0. Prerequisites",[501,2064,2065,2068,2071,2074],{},[504,2066,2067],{},"A Linux VPS",[504,2069,2070],{},"A domain pointing at your server",[504,2072,2073],{},"Docker and the Docker Compose plugin",[504,2075,2076],{},"Cloudflare account (free tier)",[428,2078,2079,2080,2082],{},"In this guide, we will run the Nostr relay on an Ubuntu VPS behind a ",[441,2081,475],{"href":363}," private network. The stack is four services in Docker Compose, relay, PostgreSQL, Redis and MinIO.",[483,2084],{"description":485,"image":486,"image-alt":487,"label":488,"min-read":489,"title":362,"to":363},[536,2086,2088],{"id":2087},"_1-cloudflare-dns-and-api-token","1. Cloudflare DNS and API Token",[541,2090,2092],{"id":2091},"create-a-cloudflare-api-token","Create a Cloudflare API Token",[2094,2095,2096,2103],"ol",{},[504,2097,2098,2099,2102],{},"Click on the top right ",[461,2100,2101],{},"Profile"," from the user icon dropdown menu.",[504,2104,2105,2106,692],{},"Click on ",[461,2107,2108],{},"API Tokens",[428,2110,2111],{},[432,2112],{"alt":2113,"src":2114},"Cloudflare user profile page showing the API Tokens creation menu","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fcloudflare-profile-api-tokens.webp",[2094,2116,2117,2123,2130,2150,2155,2159,2162],{"start":603},[504,2118,2119,2120,692],{},"Click ",[461,2121,2122],{},"Create Token",[504,2124,2125,2126,2129],{},"Use the ",[461,2127,2128],{},"Edit zone DNS"," template.",[504,2131,2132,2133],{},"Configure the template as follows:\n",[501,2134,2135,2141],{},[504,2136,2137,2140],{},[461,2138,2139],{},"Permissions",": Zone — DNS — Edit",[504,2142,2143,2146,2147],{},[461,2144,2145],{},"Zone Resources",": Include — Specific zone — ",[573,2148,2149],{},"example.com",[504,2151,2119,2152,692],{},[461,2153,2154],{},"Continue to summary",[504,2156,2119,2157,692],{},[461,2158,2122],{},[504,2160,2161],{},"Copy the generated token as it won't be shown when the page is closed.",[504,2163,2164],{},"Test the generated token in your terminal to ensure it works:",[567,2166,2168],{"className":569,"code":2167,"language":571,"meta":423,"style":423},"curl \"https:\u002F\u002Fapi.cloudflare.com\u002Fclient\u002Fv4\u002Fuser\u002Ftokens\u002Fverify\" -H \"Authorization: Bearer YOUR_TOKEN_HERE\"\n",[573,2169,2170],{"__ignoreMap":423},[576,2171,2172,2174,2176,2179,2181,2184,2186,2189],{"class":578,"line":579},[576,2173,802],{"class":582},[576,2175,1096],{"class":719},[576,2177,2178],{"class":586},"https:\u002F\u002Fapi.cloudflare.com\u002Fclient\u002Fv4\u002Fuser\u002Ftokens\u002Fverify",[576,2180,1518],{"class":719},[576,2182,2183],{"class":586}," -H",[576,2185,1096],{"class":719},[576,2187,2188],{"class":586},"Authorization: Bearer YOUR_TOKEN_HERE",[576,2190,1102],{"class":719},[541,2192,2194],{"id":2193},"dns-records","DNS Records",[501,2196,2197],{},[504,2198,2199,2200,692],{},"Create an A record and set it to ",[461,2201,550],{},[428,2203,2204],{},[432,2205],{"alt":2206,"src":2207},"Configuring a DNS A record for the Buzz domain in Cloudflare dashboard with proxy status set to DNS only","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fcloudflare-dns-a-record-configuration.webp",[536,2209,2211],{"id":2210},"_2-install-docker-on-ubuntu","2. Install Docker on Ubuntu",[428,2213,2214],{},"Run the following commands to install Docker on Ubuntu:",[567,2216,2218],{"className":569,"code":2217,"language":571,"meta":423,"style":423},"# Add Docker's official GPG key and set up the Docker repository\ncurl -fsSL https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu\u002Fgpg | sudo gpg --dearmor -o \u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg\n\n# Add the official Docker repository\necho \"deb [arch=amd64 signed-by=\u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg] https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu $(lsb_release -cs) stable\" | sudo tee \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fdocker.list > \u002Fdev\u002Fnull\n\n# Update package list\nsudo apt update\n\n# Install Docker Engine, Docker Community Edition, and containerd runtime\nsudo apt install docker-ce docker-ce-cli containerd.io -y\n\n# Start automatically when the system boots\nsudo systemctl enable docker\n\n# Verify docker is installed\ndocker --version\n\nsudo apt install -y docker-compose-plugin\n\n# Verify the compose plugin is installed\ndocker compose version\n\n",[573,2219,2220,2225,2253,2257,2262,2304,2308,2313,2323,2327,2332,2353,2357,2362,2373,2377,2382,2388,2392,2406,2410,2415],{"__ignoreMap":423},[576,2221,2222],{"class":578,"line":579},[576,2223,2224],{"class":606},"# Add Docker's official GPG key and set up the Docker repository\n",[576,2226,2227,2229,2232,2235,2238,2241,2244,2247,2250],{"class":578,"line":597},[576,2228,802],{"class":582},[576,2230,2231],{"class":586}," -fsSL",[576,2233,2234],{"class":586}," https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu\u002Fgpg",[576,2236,2237],{"class":719}," |",[576,2239,2240],{"class":582}," sudo",[576,2242,2243],{"class":586}," gpg",[576,2245,2246],{"class":586}," --dearmor",[576,2248,2249],{"class":586}," -o",[576,2251,2252],{"class":586}," \u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg\n",[576,2254,2255],{"class":578,"line":603},[576,2256,738],{"emptyLinePlaceholder":737},[576,2258,2259],{"class":578,"line":610},[576,2260,2261],{"class":606},"# Add the official Docker repository\n",[576,2263,2264,2267,2269,2272,2275,2278,2281,2284,2287,2289,2291,2293,2295,2298,2301],{"class":578,"line":620},[576,2265,2266],{"class":613},"echo",[576,2268,1096],{"class":719},[576,2270,2271],{"class":586},"deb [arch=amd64 signed-by=\u002Fusr\u002Fshare\u002Fkeyrings\u002Fdocker-archive-keyring.gpg] https:\u002F\u002Fdownload.docker.com\u002Flinux\u002Fubuntu ",[576,2273,2274],{"class":719},"$(",[576,2276,2277],{"class":582},"lsb_release",[576,2279,2280],{"class":586}," -cs",[576,2282,2283],{"class":719},")",[576,2285,2286],{"class":586}," stable",[576,2288,1518],{"class":719},[576,2290,2237],{"class":719},[576,2292,2240],{"class":582},[576,2294,1642],{"class":586},[576,2296,2297],{"class":586}," \u002Fetc\u002Fapt\u002Fsources.list.d\u002Fdocker.list",[576,2299,2300],{"class":719}," >",[576,2302,2303],{"class":586}," \u002Fdev\u002Fnull\n",[576,2305,2306],{"class":578,"line":625},[576,2307,738],{"emptyLinePlaceholder":737},[576,2309,2310],{"class":578,"line":631},[576,2311,2312],{"class":606},"# Update package list\n",[576,2314,2315,2317,2320],{"class":578,"line":772},[576,2316,1307],{"class":582},[576,2318,2319],{"class":586}," apt",[576,2321,2322],{"class":586}," update\n",[576,2324,2325],{"class":578,"line":1124},[576,2326,738],{"emptyLinePlaceholder":737},[576,2328,2329],{"class":578,"line":1132},[576,2330,2331],{"class":606},"# Install Docker Engine, Docker Community Edition, and containerd runtime\n",[576,2333,2334,2336,2338,2341,2344,2347,2350],{"class":578,"line":1140},[576,2335,1307],{"class":582},[576,2337,2319],{"class":586},[576,2339,2340],{"class":586}," install",[576,2342,2343],{"class":586}," docker-ce",[576,2345,2346],{"class":586}," docker-ce-cli",[576,2348,2349],{"class":586}," containerd.io",[576,2351,2352],{"class":586}," -y\n",[576,2354,2355],{"class":578,"line":1148},[576,2356,738],{"emptyLinePlaceholder":737},[576,2358,2359],{"class":578,"line":1156},[576,2360,2361],{"class":606},"# Start automatically when the system boots\n",[576,2363,2364,2366,2368,2370],{"class":578,"line":1164},[576,2365,1307],{"class":582},[576,2367,1748],{"class":586},[576,2369,1761],{"class":586},[576,2371,2372],{"class":586}," docker\n",[576,2374,2375],{"class":578,"line":1172},[576,2376,738],{"emptyLinePlaceholder":737},[576,2378,2379],{"class":578,"line":1183},[576,2380,2381],{"class":606},"# Verify docker is installed\n",[576,2383,2384,2386],{"class":578,"line":1188},[576,2385,787],{"class":582},[576,2387,1441],{"class":586},[576,2389,2390],{"class":578,"line":1196},[576,2391,738],{"emptyLinePlaceholder":737},[576,2393,2394,2396,2398,2400,2403],{"class":578,"line":1737},[576,2395,1307],{"class":582},[576,2397,2319],{"class":586},[576,2399,2340],{"class":586},[576,2401,2402],{"class":586}," -y",[576,2404,2405],{"class":586}," docker-compose-plugin\n",[576,2407,2408],{"class":578,"line":1743},[576,2409,738],{"emptyLinePlaceholder":737},[576,2411,2412],{"class":578,"line":1754},[576,2413,2414],{"class":606},"# Verify the compose plugin is installed\n",[576,2416,2418,2420,2422],{"class":578,"line":2417},22,[576,2419,787],{"class":582},[576,2421,790],{"class":586},[576,2423,2424],{"class":586}," version\n",[536,2426,2428],{"id":2427},"_3-clone-and-configure","3. Clone and configure",[567,2430,2432],{"className":569,"code":2431,"language":571,"meta":423,"style":423},"git clone https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz.git\n\ncd buzz\u002Fdeploy\u002Fcompose\ncp .env.example .env\nnano .env\n",[573,2433,2434,2443,2447,2454,2462],{"__ignoreMap":423},[576,2435,2436,2438,2440],{"class":578,"line":579},[576,2437,583],{"class":582},[576,2439,587],{"class":586},[576,2441,2442],{"class":586}," https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz.git\n",[576,2444,2445],{"class":578,"line":597},[576,2446,738],{"emptyLinePlaceholder":737},[576,2448,2449,2451],{"class":578,"line":603},[576,2450,614],{"class":613},[576,2452,2453],{"class":586}," buzz\u002Fdeploy\u002Fcompose\n",[576,2455,2456,2458,2460],{"class":578,"line":610},[576,2457,634],{"class":582},[576,2459,637],{"class":586},[576,2461,640],{"class":586},[576,2463,2464,2467],{"class":578,"line":620},[576,2465,2466],{"class":582},"nano",[576,2468,640],{"class":586},[428,2470,644,2471,2473],{},[573,2472,647],{}," in groups:",[501,2475,2476],{},[504,2477,2478],{},[461,2479,2480],{},"Domain:",[567,2482,2487],{"className":2483,"code":2485,"language":2486},[2484],"language-text","BUZZ_DOMAIN=buzz.pafor.me\nRELAY_URL=wss:\u002F\u002Fbuzz.pafor.me\nBUZZ_PAIRING_RELAY_URL=wss:\u002F\u002Fbuzz.pafor.me\u002Fpair\nBUZZ_MEDIA_BASE_URL=https:\u002F\u002Fbuzz.pafor.me\u002Fmedia\nBUZZ_MEDIA_SERVER_DOMAIN=buzz.pafor.me\nBUZZ_CORS_ORIGINS=https:\u002F\u002Fbuzz.pafor.me\n","text",[573,2488,2485],{"__ignoreMap":423},[501,2490,2491,2501],{},[504,2492,2493,2496,2497,2500],{},[461,2494,2495],{},"Owner key:"," ",[573,2498,2499],{},"RELAY_OWNER_PUBKEY"," requires your 64-character hex public key. Generate an identity in the desktop app first ('Create a new identity key' → copy your public ID, which is in npub format), then convert it to hex.",[504,2502,2503,2506],{},[461,2504,2505],{},"Secrets:",[501,2507,2508,2518,2532],{},[504,2509,2510,2511,2514,2515,2517],{},"Generate secrets using this ",[441,2512,2513],{"href":668},"online tool"," or with ",[573,2516,673],{}," (run it seven times)",[504,2519,2520,2521,2524,2525,1397,2528,2531],{},"Replace every ",[573,2522,2523],{},"CHANGE_ME"," placeholder: ",[573,2526,2527],{},"BUZZ_RELAY_PRIVATE_KEY",[573,2529,2530],{},"BUZZ_GIT_HOOK_HMAC_SECRET",", the Postgres\u002FRedis\u002FTypesense passwords, and the S3 access\u002Fsecret keys.",[504,2533,2534,2535,692],{},"Leftover placeholders are the most common cause of container restart loops; verify yours with ",[573,2536,2537],{},"grep CHANGE_ME .env",[567,2539,2542],{"className":2540,"code":2541,"language":2486},[2484],"    BUZZ_RELAY_PRIVATE_KEY=CHANGE_ME_64_HEX_PRIVATE_KEY\n    BUZZ_GIT_HOOK_HMAC_SECRET=CHANGE_ME_RANDOM_64_HEX\n    POSTGRES_PASSWORD=CHANGE_ME_RANDOM_PASSWORD\n    REDIS_PASSWORD=CHANGE_ME_RANDOM_PASSWORD\n    TYPESENSE_API_KEY=CHANGE_ME_RANDOM_API_KEY\n    BUZZ_S3_ACCESS_KEY=CHANGE_ME_RANDOM_ACCESS_KEY\n    BUZZ_S3_SECRET_KEY=CHANGE_ME_RANDOM_SECRET_KEY\n",[573,2543,2541],{"__ignoreMap":423},[501,2545,2546],{},[504,2547,2548,2551],{},[461,2549,2550],{},"Others:",[501,2552,2553,2559],{},[504,2554,1002,2555,2558],{},[573,2556,2557],{},"CLOUDFLARE_API_TOKEN"," as an environment variable and assign the API token generated earlier. This is required for Caddy.",[504,2560,2561,2562,1397,2564,1401,2567,692],{},"Buzz ships with open defaults — anyone who knows your relay URL can authenticate and join. Set ",[573,2563,2499],{},[573,2565,2566],{},"BUZZ_REQUIRE_RELAY_MEMBERSHIP=true",[573,2568,2569],{},"BUZZ_REQUIRE_AUTH_TOKEN=true",[536,2571,2573],{"id":2572},"_4-enable-https-with-caddy","4. Enable HTTPS with Caddy",[541,2575,2577],{"id":2576},"build-a-custom-caddy-image-with-the-cloudflare-dns-module","Build a Custom Caddy Image with the Cloudflare DNS Module",[501,2579,2580,2591,2602],{},[504,2581,2582,2583,2586,2587,2590],{},"We set up DNS-01 with Cloudflare for Caddy. DNS-01 works by having the plugin write a TXT record ",[573,2584,2585],{},"_acme-challenge.buzz.pafor.me"," to the ",[461,2588,2589],{},"public DNS",";",[504,2592,2593,2594,2597,2598,2601],{},"Let's Encrypt then looks the record up from the public internet to verify domain control. This means ",[573,2595,2596],{},"pafor.me"," must be a public zone in your Cloudflare account — not just a private hostname that only exists in Zero Trust \u002F WARP private DNS. If ",[573,2599,2600],{},"buzz.pafor.me"," is only resolved privately and there is no public zone, DNS-01 will fail, requiring a different approach.",[504,2603,2604],{},"Add the following to the Caddyfile:",[567,2606,2608],{"className":1052,"code":2607,"language":1054,"meta":423,"style":423},"{\n  acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}\n}\n",[573,2609,2610,2614,2627],{"__ignoreMap":423},[576,2611,2612],{"class":578,"line":579},[576,2613,720],{"class":719},[576,2615,2616,2619,2622,2625],{"class":578,"line":597},[576,2617,2618],{"class":586},"  acme_dns cloudflare",[576,2620,2621],{"class":719}," {",[576,2623,2624],{"class":586},"env.CLOUDFLARE_API_TOKEN",[576,2626,728],{"class":719},[576,2628,2629],{"class":578,"line":603},[576,2630,728],{"class":719},[501,2632,2633],{},[504,2634,2635],{},"Create a Dockerfile.caddy with the following content, which is required by compose.caddy.yml:",[567,2637,2639],{"className":1052,"code":2638,"language":1054,"meta":423,"style":423},"FROM caddy:2-builder AS builder\n\nRUN xcaddy build \\\n    --with github.com\u002Fcaddy-dns\u002Fcloudflare\n\nFROM caddy:2-alpine\n\nCOPY --from=builder \u002Fusr\u002Fbin\u002Fcaddy \u002Fusr\u002Fbin\u002Fcaddy\n",[573,2640,2641,2646,2650,2655,2660,2664,2669,2673],{"__ignoreMap":423},[576,2642,2643],{"class":578,"line":579},[576,2644,2645],{"class":586},"FROM caddy:2-builder AS builder\n",[576,2647,2648],{"class":578,"line":597},[576,2649,738],{"emptyLinePlaceholder":737},[576,2651,2652],{"class":578,"line":603},[576,2653,2654],{"class":586},"RUN xcaddy build \\\n",[576,2656,2657],{"class":578,"line":610},[576,2658,2659],{"class":586},"    --with github.com\u002Fcaddy-dns\u002Fcloudflare\n",[576,2661,2662],{"class":578,"line":620},[576,2663,738],{"emptyLinePlaceholder":737},[576,2665,2666],{"class":578,"line":625},[576,2667,2668],{"class":586},"FROM caddy:2-alpine\n",[576,2670,2671],{"class":578,"line":631},[576,2672,738],{"emptyLinePlaceholder":737},[576,2674,2675],{"class":578,"line":772},[576,2676,2677],{"class":586},"COPY --from=builder \u002Fusr\u002Fbin\u002Fcaddy \u002Fusr\u002Fbin\u002Fcaddy\n",[501,2679,2680],{},[504,2681,2682,2683,2686],{},"Modify ",[573,2684,2685],{},"compose.caddy.yml"," to use the image with the Cloudflare module and pass the Cloudflare API token:",[567,2688,2690],{"className":1052,"code":2689,"language":1054,"meta":423,"style":423},"services:\n  relay:\n    ports: !reset []\n\n  caddy:\n    build:\n      context: .\n      dockerfile: Dockerfile.caddy\n    image: buzz-caddy:cloudflare\n    depends_on:\n      relay:\n        condition: service_healthy\n    environment:\n      BUZZ_DOMAIN: ${BUZZ_DOMAIN:?set BUZZ_DOMAIN}\n      CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN:?set CLOUDFLARE_API_TOKEN}\n    ports:\n      - \"${CADDY_HTTP_PORT:-80}:80\"\n      - \"${CADDY_HTTPS_PORT:-443}:443\"\n    volumes:\n      - .\u002FCaddyfile:\u002Fetc\u002Fcaddy\u002FCaddyfile:ro\n      - buzz-caddy-data:\u002Fdata\n      - buzz-caddy-config:\u002Fconfig\n    restart: unless-stopped\n    networks:\n      - buzz-net\n\nvolumes:\n  buzz-caddy-data:\n    labels:\n      com.buzz.volume: caddy-data\n  buzz-caddy-config:\n    labels:\n      com.buzz.volume: caddy-config\n",[573,2691,2692,2698,2705,2718,2722,2729,2736,2746,2756,2765,2772,2779,2789,2795,2805,2815,2821,2832,2843,2849,2856,2863,2870,2879,2887,2895,2900,2907,2915,2923,2934,2942,2949],{"__ignoreMap":423},[576,2693,2694,2696],{"class":578,"line":579},[576,2695,1062],{"class":1061},[576,2697,914],{"class":719},[576,2699,2700,2703],{"class":578,"line":597},[576,2701,2702],{"class":1061},"  relay",[576,2704,914],{"class":719},[576,2706,2707,2709,2711,2715],{"class":578,"line":603},[576,2708,1086],{"class":1061},[576,2710,765],{"class":719},[576,2712,2714],{"class":2713},"spNyl"," !reset",[576,2716,2717],{"class":719}," []\n",[576,2719,2720],{"class":578,"line":610},[576,2721,738],{"emptyLinePlaceholder":737},[576,2723,2724,2727],{"class":578,"line":620},[576,2725,2726],{"class":1061},"  caddy",[576,2728,914],{"class":719},[576,2730,2731,2734],{"class":578,"line":625},[576,2732,2733],{"class":1061},"    build",[576,2735,914],{"class":719},[576,2737,2738,2741,2743],{"class":578,"line":631},[576,2739,2740],{"class":1061},"      context",[576,2742,765],{"class":719},[576,2744,2745],{"class":768}," .\n",[576,2747,2748,2751,2753],{"class":578,"line":772},[576,2749,2750],{"class":1061},"      dockerfile",[576,2752,765],{"class":719},[576,2754,2755],{"class":586}," Dockerfile.caddy\n",[576,2757,2758,2760,2762],{"class":578,"line":1124},[576,2759,1076],{"class":1061},[576,2761,765],{"class":719},[576,2763,2764],{"class":586}," buzz-caddy:cloudflare\n",[576,2766,2767,2770],{"class":578,"line":1132},[576,2768,2769],{"class":1061},"    depends_on",[576,2771,914],{"class":719},[576,2773,2774,2777],{"class":578,"line":1140},[576,2775,2776],{"class":1061},"      relay",[576,2778,914],{"class":719},[576,2780,2781,2784,2786],{"class":578,"line":1148},[576,2782,2783],{"class":1061},"        condition",[576,2785,765],{"class":719},[576,2787,2788],{"class":586}," service_healthy\n",[576,2790,2791,2793],{"class":578,"line":1156},[576,2792,1107],{"class":1061},[576,2794,914],{"class":719},[576,2796,2797,2800,2802],{"class":578,"line":1164},[576,2798,2799],{"class":1061},"      BUZZ_DOMAIN",[576,2801,765],{"class":719},[576,2803,2804],{"class":586}," ${BUZZ_DOMAIN:?set BUZZ_DOMAIN}\n",[576,2806,2807,2810,2812],{"class":578,"line":1172},[576,2808,2809],{"class":1061},"      CLOUDFLARE_API_TOKEN",[576,2811,765],{"class":719},[576,2813,2814],{"class":586}," ${CLOUDFLARE_API_TOKEN:?set CLOUDFLARE_API_TOKEN}\n",[576,2816,2817,2819],{"class":578,"line":1183},[576,2818,1086],{"class":1061},[576,2820,914],{"class":719},[576,2822,2823,2825,2827,2830],{"class":578,"line":1188},[576,2824,1093],{"class":719},[576,2826,1096],{"class":719},[576,2828,2829],{"class":586},"${CADDY_HTTP_PORT:-80}:80",[576,2831,1102],{"class":719},[576,2833,2834,2836,2838,2841],{"class":578,"line":1196},[576,2835,1093],{"class":719},[576,2837,1096],{"class":719},[576,2839,2840],{"class":586},"${CADDY_HTTPS_PORT:-443}:443",[576,2842,1102],{"class":719},[576,2844,2845,2847],{"class":578,"line":1737},[576,2846,1143],{"class":1061},[576,2848,914],{"class":719},[576,2850,2851,2853],{"class":578,"line":1743},[576,2852,1093],{"class":719},[576,2854,2855],{"class":586}," .\u002FCaddyfile:\u002Fetc\u002Fcaddy\u002FCaddyfile:ro\n",[576,2857,2858,2860],{"class":578,"line":1754},[576,2859,1093],{"class":719},[576,2861,2862],{"class":586}," buzz-caddy-data:\u002Fdata\n",[576,2864,2865,2867],{"class":578,"line":2417},[576,2866,1093],{"class":719},[576,2868,2869],{"class":586}," buzz-caddy-config:\u002Fconfig\n",[576,2871,2873,2875,2877],{"class":578,"line":2872},23,[576,2874,1175],{"class":1061},[576,2876,765],{"class":719},[576,2878,1180],{"class":586},[576,2880,2882,2885],{"class":578,"line":2881},24,[576,2883,2884],{"class":1061},"    networks",[576,2886,914],{"class":719},[576,2888,2890,2892],{"class":578,"line":2889},25,[576,2891,1093],{"class":719},[576,2893,2894],{"class":586}," buzz-net\n",[576,2896,2898],{"class":578,"line":2897},26,[576,2899,738],{"emptyLinePlaceholder":737},[576,2901,2903,2905],{"class":578,"line":2902},27,[576,2904,1191],{"class":1061},[576,2906,914],{"class":719},[576,2908,2910,2913],{"class":578,"line":2909},28,[576,2911,2912],{"class":1061},"  buzz-caddy-data",[576,2914,914],{"class":719},[576,2916,2918,2921],{"class":578,"line":2917},29,[576,2919,2920],{"class":1061},"    labels",[576,2922,914],{"class":719},[576,2924,2926,2929,2931],{"class":578,"line":2925},30,[576,2927,2928],{"class":1061},"      com.buzz.volume",[576,2930,765],{"class":719},[576,2932,2933],{"class":586}," caddy-data\n",[576,2935,2937,2940],{"class":578,"line":2936},31,[576,2938,2939],{"class":1061},"  buzz-caddy-config",[576,2941,914],{"class":719},[576,2943,2945,2947],{"class":578,"line":2944},32,[576,2946,2920],{"class":1061},[576,2948,914],{"class":719},[576,2950,2952,2954,2956],{"class":578,"line":2951},33,[576,2953,2928],{"class":1061},[576,2955,765],{"class":719},[576,2957,2958],{"class":586}," caddy-config\n",[541,2960,2962],{"id":2961},"start-the-docker-containers","Start the Docker containers",[567,2964,2966],{"className":569,"code":2965,"language":571,"meta":423,"style":423},"docker compose -f compose.yml -f compose.caddy.yml up -d\n\n#Check the Docker status\ndocker compose ps\n",[573,2967,2968,2988,2992,2997],{"__ignoreMap":423},[576,2969,2970,2972,2974,2976,2979,2981,2984,2986],{"class":578,"line":579},[576,2971,787],{"class":582},[576,2973,790],{"class":586},[576,2975,1255],{"class":586},[576,2977,2978],{"class":586}," compose.yml",[576,2980,1255],{"class":586},[576,2982,2983],{"class":586}," compose.caddy.yml",[576,2985,793],{"class":586},[576,2987,796],{"class":586},[576,2989,2990],{"class":578,"line":597},[576,2991,738],{"emptyLinePlaceholder":737},[576,2993,2994],{"class":578,"line":603},[576,2995,2996],{"class":606},"#Check the Docker status\n",[576,2998,2999,3001,3003],{"class":578,"line":610},[576,3000,787],{"class":582},[576,3002,790],{"class":586},[576,3004,3005],{"class":586}," ps\n",[432,3007],{"src":3008,"alt":3009,"style":3010},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fdocker-compose-ps-status-terminal.webp","Terminal window displaying running containers for Buzz services via docker compose ps","max-width: 700px; width: 100%; height: auto;",[428,3012,3013,3014,3017],{},"Open your web browser and navigate to ",[573,3015,3016],{},"http:\u002F\u002Fbuzz.pafor.me"," to verify that the relay is running.",[432,3019],{"src":3020,"alt":3021,"style":927},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-relay-running-browser-verification.webp","Browser verification showing successful response from self-hosted Block's Buzz relay",[536,3023,3025],{"id":3024},"step-5-back-up-from-day-one","Step 5: Back up from day one",[567,3027,3029],{"className":569,"code":3028,"language":571,"meta":423,"style":423},"mkdir -p \u002Fbuzz_backups\ncrontab -e\n",[573,3030,3031,3042],{"__ignoreMap":423},[576,3032,3033,3036,3039],{"class":578,"line":579},[576,3034,3035],{"class":582},"mkdir",[576,3037,3038],{"class":586}," -p",[576,3040,3041],{"class":586}," \u002Fbuzz_backups\n",[576,3043,3044,3047],{"class":578,"line":597},[576,3045,3046],{"class":582},"crontab",[576,3048,3049],{"class":586}," -e\n",[428,3051,3052],{},"Add a nightly database dump cron job:",[567,3054,3057],{"className":3055,"code":3056,"language":2486},[2484],"0 3 * * * cd \u002Fhome\u002F\u003Cuser>\u002Fbuzz\u002Fdeploy\u002Fcompose && docker compose exec -T postgres pg_dump -U buzz buzz > \u002Fbuzz_backups\u002Fbuzz-$(date +\\%Y\\%m\\%d).sql\n",[573,3058,3056],{"__ignoreMap":423},[428,3060,3061],{},"Note: Treat BUZZ_RELAY_PRIVATE_KEY as permanent. Events signed by it will fail verification if the key changes; a restored database paired with a fresh key is not treated as the same relay.",[491,3063,3065],{"id":3064},"setting-up-the-buzz-desktop-client-and-nostr-identities","Setting Up the Buzz Desktop Client and Nostr Identities",[428,3067,3068,3069,3073],{},"Download the Buzz desktop app from ",[441,3070,3071],{"href":3071,"rel":3072},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz\u002Freleases",[445]," and start it. Fill in the profile details until you reach the \"Join or create a community\" page.",[428,3075,3076],{},[432,3077],{"alt":3078,"src":3079},"Buzz Desktop Client initial setup screen for joining or creating a community","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-setup-community.webp",[428,3081,3082],{},"Click \"Join a community\" and copy your public key.",[428,3084,3085],{},[432,3086],{"alt":3087,"src":3088},"Buzz client display showing public key identity before joining community","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-join-community-public-key.webp",[428,3090,3091,3092,3094],{},"Run the following command on the ",[461,3093,469],{}," to add yourself as the first member:",[567,3096,3098],{"className":569,"code":3097,"language":571,"meta":423,"style":423},"docker compose exec relay buzz-admin add-member --pubkey npub1yourkeyhere\n",[573,3099,3100],{"__ignoreMap":423},[576,3101,3102,3104,3106,3109,3112,3115,3118,3121],{"class":578,"line":579},[576,3103,787],{"class":582},[576,3105,790],{"class":586},[576,3107,3108],{"class":586}," exec",[576,3110,3111],{"class":586}," relay",[576,3113,3114],{"class":586}," buzz-admin",[576,3116,3117],{"class":586}," add-member",[576,3119,3120],{"class":586}," --pubkey",[576,3122,3123],{"class":586}," npub1yourkeyhere\n",[428,3125,1002,3126,3129],{},[573,3127,3128],{},"wss:\u002F\u002Fbuzz.pafor.me"," as the community URL and click \"Next\".",[428,3131,3132],{},[432,3133],{"alt":3134,"src":3135},"Entering the self-hosted community relay URL in the Buzz desktop app","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-input-community-url.webp",[428,3137,3138],{},"Enter a name and click the Next button.",[428,3140,3141],{},[432,3142],{"alt":3143,"src":3144},"Profile configuration screen in Buzz app to enter display name","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-profile-name-input.webp",[536,3146,3148],{"id":3147},"channels-and-agents","Channels and Agents",[428,3150,3151],{},"Channels are task groups or project groups. Create a channel per task or project and pull the humans and agents in.",[428,3153,3154],{},"Everything within a channel is shared automatically, eliminating the need to brief each member individually. Every agent can be mentioned using @ and reads the relevant messages. Also, agents can @ each other.",[428,3156,3157],{},"Let's send a DM to a preconfigured agent",[428,3159,3160],{},[432,3161],{"alt":3162,"src":3163},"Sending direct message to an AI agent in the Buzz collaborative desktop client","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-dm-agent.webp",[428,3165,3166],{},"Let's create a channel and add some agents to it",[428,3168,3169],{},[432,3170],{"alt":3171,"src":3172},"Creating a new task or project channel inside the Buzz desktop app","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-create-channel-dialog.webp",[428,3174,3175],{},[432,3176],{"alt":3177,"src":3178},"Adding human members and AI agents to the newly created channel","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-add-agents-to-channel.webp",[428,3180,3181],{},[432,3182],{"alt":3183,"src":3184},"Active channel view displaying consolidated chat history and project tasks","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-channel-view.webp",[432,3186],{"src":3187,"alt":3188,"style":3189},"https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-channel-active-agents.webp","Detail view of active AI agents integrated into the collaborative project channel","max-width: 367px; width: 100%; height: auto;",[536,3191,3193],{"id":3192},"enable-agent-runtimes","Enable Agent Runtimes",[428,3195,3196,3197,3200,3201,3204],{},"Preset runtimes rely on auto-discovery detecting launcher binaries (e.g. ",[573,3198,3199],{},"hermes-acp",") in standard directories like ",[573,3202,3203],{},"~\u002F.local\u002Fbin",". If a tool was installed in a non-standard location, Buzz cannot resolve it.",[428,3206,3207,3208,3211],{},"For Kimi Code, the agent ID is kimi, and Buzz looks for its binary at ",[573,3209,3210],{},"~\u002F.local\u002Fbin\u002Fkimi",". A symbolic link does the job:",[567,3213,3216],{"className":3214,"code":3215,"language":2486},[2484],"ln -s kimi-cli \u002FUsers\u002F\u003Cuser>\u002F.local\u002Fbin\u002Fkimi\n",[573,3217,3215],{"__ignoreMap":423},[428,3219,3220],{},"Kimi Code now appears under Agent runtimes.",[428,3222,3223],{},[432,3224],{"alt":3225,"src":3226},"Buzz application settings displaying configured AI Agent runtimes including Kimi","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-settings-agent-runtimes-list.webp",[536,3228,3230],{"id":3229},"projects-and-repositories","Projects and Repositories",[428,3232,3233,3234,3237],{},"Enable the '",[461,3235,3236],{},"Projects","' feature in Settings → Experiments first:",[428,3239,3240],{},[432,3241],{"alt":3242,"src":3243},"Enabling experimental Projects feature in the Buzz desktop settings tab","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-settings-experiments-projects.webp",[428,3245,3246,3247,3250],{},"Currently, a project must be created using the ",[573,3248,3249],{},"buzz-cli"," (though direct project creation from the UI is planned for a future release).",[541,3252,3254],{"id":3253},"install-buzz-cli","Install buzz-cli",[428,3256,3257,3258,3260,3261,765],{},"Run the following commands to install ",[573,3259,3249],{}," on the ",[461,3262,469],{},[567,3264,3266],{"className":569,"code":3265,"language":571,"meta":423,"style":423},"sudo apt install cargo\ncd ~\u002Fbuzz\ncargo install --path crates\u002Fbuzz-cli\necho 'export PATH=\"$HOME\u002F.cargo\u002Fbin:$PATH\"' >> ~\u002F.bashrc && source ~\u002F.bashrc\n",[573,3267,3268,3279,3286,3299],{"__ignoreMap":423},[576,3269,3270,3272,3274,3276],{"class":578,"line":579},[576,3271,1307],{"class":582},[576,3273,2319],{"class":586},[576,3275,2340],{"class":586},[576,3277,3278],{"class":586}," cargo\n",[576,3280,3281,3283],{"class":578,"line":597},[576,3282,614],{"class":613},[576,3284,3285],{"class":586}," ~\u002Fbuzz\n",[576,3287,3288,3291,3293,3296],{"class":578,"line":603},[576,3289,3290],{"class":582},"cargo",[576,3292,2340],{"class":586},[576,3294,3295],{"class":586}," --path",[576,3297,3298],{"class":586}," crates\u002Fbuzz-cli\n",[576,3300,3301,3303,3306,3309,3312,3315,3318,3321,3324],{"class":578,"line":610},[576,3302,2266],{"class":613},[576,3304,3305],{"class":719}," '",[576,3307,3308],{"class":586},"export PATH=\"$HOME\u002F.cargo\u002Fbin:$PATH\"",[576,3310,3311],{"class":719},"'",[576,3313,3314],{"class":719}," >>",[576,3316,3317],{"class":586}," ~\u002F.bashrc",[576,3319,3320],{"class":719}," &&",[576,3322,3323],{"class":613}," source",[576,3325,3326],{"class":586}," ~\u002F.bashrc\n",[428,3328,3329,3330,3333,3334,3336,3337,3339],{},"Generate a pair of private and public keys using the ",[441,3331,2513],{"href":3332},"\u002Ftools\u002Fnostr-key-generator"," or ",[573,3335,3249],{},". This pair is the identity of the ",[573,3338,3249],{}," in Nostr relay.",[567,3341,3343],{"className":569,"code":3342,"language":571,"meta":423,"style":423},"docker run --rm --entrypoint \u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-admin ghcr.io\u002Fblock\u002Fbuzz:main generate-key\n\n# Use the generated Public Key\ndocker compose exec relay buzz-admin add-member --pubkey generated_Public_key\n",[573,3344,3345,3367,3371,3376],{"__ignoreMap":423},[576,3346,3347,3349,3352,3355,3358,3361,3364],{"class":578,"line":579},[576,3348,787],{"class":582},[576,3350,3351],{"class":586}," run",[576,3353,3354],{"class":586}," --rm",[576,3356,3357],{"class":586}," --entrypoint",[576,3359,3360],{"class":586}," \u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-admin",[576,3362,3363],{"class":586}," ghcr.io\u002Fblock\u002Fbuzz:main",[576,3365,3366],{"class":586}," generate-key\n",[576,3368,3369],{"class":578,"line":597},[576,3370,738],{"emptyLinePlaceholder":737},[576,3372,3373],{"class":578,"line":603},[576,3374,3375],{"class":606},"# Use the generated Public Key\n",[576,3377,3378,3380,3382,3384,3386,3388,3390,3392],{"class":578,"line":610},[576,3379,787],{"class":582},[576,3381,790],{"class":586},[576,3383,3108],{"class":586},[576,3385,3111],{"class":586},[576,3387,3114],{"class":586},[576,3389,3117],{"class":586},[576,3391,3120],{"class":586},[576,3393,3394],{"class":586}," generated_Public_key\n",[428,3396,3397],{},"Configure the CLI:",[567,3399,3401],{"className":569,"code":3400,"language":571,"meta":423,"style":423},"# Copy the Secret key as the BUZZ_PRIVATE_KEY\necho 'export BUZZ_PRIVATE_KEY=\"nsec1...\"'  >> \u002Fhome\u002F\u003Cuser>\u002F.bashrc\n\necho 'export BUZZ_RELAY_URL=\"wss:\u002F\u002Fbuzz.pafor.me\"'  >> \u002Fhome\u002F\u003Cuser>\u002F.bashrc\n",[573,3402,3403,3408,3440,3444],{"__ignoreMap":423},[576,3404,3405],{"class":578,"line":579},[576,3406,3407],{"class":606},"# Copy the Secret key as the BUZZ_PRIVATE_KEY\n",[576,3409,3410,3412,3414,3417,3419,3422,3425,3428,3431,3434,3437],{"class":578,"line":597},[576,3411,2266],{"class":613},[576,3413,3305],{"class":719},[576,3415,3416],{"class":586},"export BUZZ_PRIVATE_KEY=\"nsec1...\"",[576,3418,3311],{"class":719},[576,3420,3421],{"class":719},"  >>",[576,3423,3424],{"class":586}," \u002Fhome\u002F",[576,3426,3427],{"class":719},"\u003C",[576,3429,3430],{"class":586},"use",[576,3432,3433],{"class":593},"r",[576,3435,3436],{"class":719},">",[576,3438,3439],{"class":586},"\u002F.bashrc\n",[576,3441,3442],{"class":578,"line":603},[576,3443,738],{"emptyLinePlaceholder":737},[576,3445,3446,3448,3450,3453,3455,3457,3459,3461,3463,3465,3467],{"class":578,"line":610},[576,3447,2266],{"class":613},[576,3449,3305],{"class":719},[576,3451,3452],{"class":586},"export BUZZ_RELAY_URL=\"wss:\u002F\u002Fbuzz.pafor.me\"",[576,3454,3311],{"class":719},[576,3456,3421],{"class":719},[576,3458,3424],{"class":586},[576,3460,3427],{"class":719},[576,3462,3430],{"class":586},[576,3464,3433],{"class":593},[576,3466,3436],{"class":719},[576,3468,3439],{"class":586},[428,3470,3471,3472,3474],{},"Run the following command to verify ",[573,3473,3249],{}," is configured properly:",[567,3476,3478],{"className":569,"code":3477,"language":571,"meta":423,"style":423},"buzz channels list\n",[573,3479,3480],{"__ignoreMap":423},[576,3481,3482,3485,3488],{"class":578,"line":579},[576,3483,3484],{"class":582},"buzz",[576,3486,3487],{"class":586}," channels",[576,3489,3490],{"class":586}," list\n",[428,3492,3493],{},[432,3494],{"alt":3495,"src":3496},"Terminal command execution verifying buzz-cli configuration by listing active channels","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-cli-channels-list-terminal.webp",[541,3498,3500],{"id":3499},"create-a-project-with-buzz-cli","Create a Project with buzz-cli",[567,3502,3504],{"className":569,"code":3503,"language":571,"meta":423,"style":423},"# --channel refers to the UUID of the channel\nbuzz repos create --id TestKOA --name 'Display Name' --channel \"bd92b3d1-8fac-441c-a9ac-2b2f3aac5c5b\"\n",[573,3505,3506,3511],{"__ignoreMap":423},[576,3507,3508],{"class":578,"line":579},[576,3509,3510],{"class":606},"# --channel refers to the UUID of the channel\n",[576,3512,3513,3515,3518,3521,3524,3527,3530,3532,3535,3537,3540,3542,3545],{"class":578,"line":597},[576,3514,3484],{"class":582},[576,3516,3517],{"class":586}," repos",[576,3519,3520],{"class":586}," create",[576,3522,3523],{"class":586}," --id",[576,3525,3526],{"class":586}," TestKOA",[576,3528,3529],{"class":586}," --name",[576,3531,3305],{"class":719},[576,3533,3534],{"class":586},"Display Name",[576,3536,3311],{"class":719},[576,3538,3539],{"class":586}," --channel",[576,3541,1096],{"class":719},[576,3543,3544],{"class":586},"bd92b3d1-8fac-441c-a9ac-2b2f3aac5c5b",[576,3546,1102],{"class":719},[428,3548,3549,3550,3552],{},"A project can only be removed by its owner. Because the \"Display Name\" project was created by the ",[573,3551,3249],{},", which lacks a removal command, it cannot be deleted this way.",[428,3554,3555],{},"Check back the Buzz desktop app to verify the project is created.",[428,3557,3558],{},[432,3559],{"alt":3560,"src":3561},"Buzz desktop application projects view confirming successful project creation","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-project-view.webp",[428,3563,3564],{},"Once a project is available in Projects, more projects can be added using the \"+\" button at the top right corner.",[428,3566,3567],{},[432,3568],{"alt":3569,"src":3570},"Adding new developer projects using the plus icon in Buzz desktop client","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-add-project-button.webp",[541,3572,3574],{"id":3573},"check-in-existing-git-repositories","Check In Existing Git Repositories",[428,3576,3577,3578,3581,3582,3585,3586,765],{},"Install ",[573,3579,3580],{},"git-credential-nostr"," on the machine where git repositories are. It requires ",[461,3583,3584],{},"git 2.46+"," and the Rust toolchain. Refer to this ",[441,3587,3590],{"href":3588,"rel":3589},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz\u002Ftree\u002Fmain\u002Fcrates\u002Fgit-credential-nostr",[445],"Readme",[567,3592,3594],{"className":569,"code":3593,"language":571,"meta":423,"style":423},"cargo install --path crates\u002Fgit-credential-nostr\n",[573,3595,3596],{"__ignoreMap":423},[576,3597,3598,3600,3602,3604],{"class":578,"line":579},[576,3599,3290],{"class":582},[576,3601,2340],{"class":586},[576,3603,3295],{"class":586},[576,3605,3606],{"class":586}," crates\u002Fgit-credential-nostr\n",[428,3608,3609,3610,3612],{},"Set up ",[573,3611,3580],{}," for Buzz relay authorisation:",[567,3614,3616],{"className":569,"code":3615,"language":571,"meta":423,"style":423},"# 1. Register the helper and enable per-path credentials.\ngit config --global credential.helper nostr\ngit config --global credential.useHttpPath true\n\n# 2. Store your nsec in a key file (must be 0600). Replace \"nsec1...\" with your private key\nmkdir -p ~\u002F.nostr\necho \"nsec1...\" > ~\u002F.nostr\u002Fkey && chmod 600 ~\u002F.nostr\u002Fkey\ngit config --global nostr.keyfile ~\u002F.nostr\u002Fkey\n",[573,3617,3618,3623,3639,3653,3657,3662,3671,3698],{"__ignoreMap":423},[576,3619,3620],{"class":578,"line":579},[576,3621,3622],{"class":606},"# 1. Register the helper and enable per-path credentials.\n",[576,3624,3625,3627,3630,3633,3636],{"class":578,"line":597},[576,3626,583],{"class":582},[576,3628,3629],{"class":586}," config",[576,3631,3632],{"class":586}," --global",[576,3634,3635],{"class":586}," credential.helper",[576,3637,3638],{"class":586}," nostr\n",[576,3640,3641,3643,3645,3647,3650],{"class":578,"line":603},[576,3642,583],{"class":582},[576,3644,3629],{"class":586},[576,3646,3632],{"class":586},[576,3648,3649],{"class":586}," credential.useHttpPath",[576,3651,3652],{"class":719}," true\n",[576,3654,3655],{"class":578,"line":610},[576,3656,738],{"emptyLinePlaceholder":737},[576,3658,3659],{"class":578,"line":620},[576,3660,3661],{"class":606},"# 2. Store your nsec in a key file (must be 0600). Replace \"nsec1...\" with your private key\n",[576,3663,3664,3666,3668],{"class":578,"line":625},[576,3665,3035],{"class":582},[576,3667,3038],{"class":586},[576,3669,3670],{"class":586}," ~\u002F.nostr\n",[576,3672,3673,3675,3677,3680,3682,3684,3687,3689,3692,3695],{"class":578,"line":631},[576,3674,2266],{"class":613},[576,3676,1096],{"class":719},[576,3678,3679],{"class":586},"nsec1...",[576,3681,1518],{"class":719},[576,3683,2300],{"class":719},[576,3685,3686],{"class":586}," ~\u002F.nostr\u002Fkey",[576,3688,3320],{"class":719},[576,3690,3691],{"class":582}," chmod",[576,3693,3694],{"class":768}," 600",[576,3696,3697],{"class":586}," ~\u002F.nostr\u002Fkey\n",[576,3699,3700,3702,3704,3706,3709],{"class":578,"line":772},[576,3701,583],{"class":582},[576,3703,3629],{"class":586},[576,3705,3632],{"class":586},[576,3707,3708],{"class":586}," nostr.keyfile",[576,3710,3697],{"class":586},[428,3712,3713],{},"Create a repo on the Buzz relay:",[567,3715,3718],{"className":3716,"code":3717,"language":2486},[2484],"buzz repos create --id koa-email-routing --name \"KOA Email Routing\" --clone \"https:\u002F\u002Fbuzz.pafor.me\u002Fgit\u002F\u003Cpub_key>\u002Fkoa-email-routing\" --nostr-relay \"wss:\u002F\u002Fbuzz.pafor.me\"\n",[573,3719,3717],{"__ignoreMap":423},[428,3721,3722,3723,3726,3727,3730],{},"On your first ",[573,3724,3725],{},"git push",", you will encounter a ",[573,3728,3729],{},"remote: missing Authorization header"," error. To resolve this, you need to bind the repository ID to a Buzz channel, as channel membership dictates Git write permissions (ACLs):",[567,3732,3734],{"className":569,"code":3733,"language":571,"meta":423,"style":423},"buzz repos bind --id koa-email-routing --channel \u003CCHANNEL_UUID>\n\n# push the code again\ngit push\n",[573,3735,3736,3764,3768,3773],{"__ignoreMap":423},[576,3737,3738,3740,3742,3745,3747,3750,3752,3755,3758,3761],{"class":578,"line":579},[576,3739,3484],{"class":582},[576,3741,3517],{"class":586},[576,3743,3744],{"class":586}," bind",[576,3746,3523],{"class":586},[576,3748,3749],{"class":586}," koa-email-routing",[576,3751,3539],{"class":586},[576,3753,3754],{"class":719}," \u003C",[576,3756,3757],{"class":586},"CHANNEL_UUI",[576,3759,3760],{"class":593},"D",[576,3762,3763],{"class":719},">\n",[576,3765,3766],{"class":578,"line":597},[576,3767,738],{"emptyLinePlaceholder":737},[576,3769,3770],{"class":578,"line":603},[576,3771,3772],{"class":606},"# push the code again\n",[576,3774,3775,3777],{"class":578,"line":610},[576,3776,583],{"class":582},[576,3778,3779],{"class":586}," push\n",[428,3781,3782,3783,3785],{},"Checking the project in the Buzz desktop app shows the following, because the app needs ",[461,3784,3584],{}," — launching the app directly may pick up an older version of Git:",[428,3787,3788],{},[432,3789],{"alt":3790,"src":3791},"Buzz client rendering Git loading error due to outdated local Git version below 2.46","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-git-version-error.webp",[428,3793,3794,3795,3798,3799,692],{},"Export the PATH via ",[573,3796,3797],{},"launchctl setenv PATH \"\u002Fopt\u002Fhomebrew\u002Fbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin:\u002Fbin:\u002Fusr\u002Fsbin:\u002Fsbin\""," in the shell profile and launch the Buzz app from the shell. Refer to this ",[441,3800,3803],{"href":3801,"rel":3802},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz\u002Fissues\u002F5348",[445],"issue",[567,3805,3807],{"className":569,"code":3806,"language":571,"meta":423,"style":423},"open -a Buzz\n",[573,3808,3809],{"__ignoreMap":423},[576,3810,3811,3814,3817],{"class":578,"line":579},[576,3812,3813],{"class":582},"open",[576,3815,3816],{"class":586}," -a",[576,3818,3819],{"class":586}," Buzz\n",[428,3821,3822],{},"Check back the Projects in the Buzz app, the repository details are now loaded.",[428,3824,3825],{},[432,3826],{"alt":3827,"src":3828},"Buzz desktop interface with successfully loaded Git repository details and commit logs","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-repository-details-loaded.webp",[491,3830,3832],{"id":3831},"syncing-ai-agents-with-the-buzz-mobile-app-via-qr-code","Syncing AI Agents with the Buzz Mobile App via QR Code",[428,3834,3835,3836,3839,3840,692],{},"The Buzz mobile app pairing only accepts the HTTPS protocol and the ",[573,3837,3838],{},"buzz-pair-relay"," is not started by default on ",[461,3841,469],{},[567,3843,3845],{"className":569,"code":3844,"language":571,"meta":423,"style":423},"cd ~\u002Fbuzz\ncargo install --path crates\u002Fbuzz-pair-relay\n",[573,3846,3847,3853],{"__ignoreMap":423},[576,3848,3849,3851],{"class":578,"line":579},[576,3850,614],{"class":613},[576,3852,3285],{"class":586},[576,3854,3855,3857,3859,3861],{"class":578,"line":597},[576,3856,3290],{"class":582},[576,3858,2340],{"class":586},[576,3860,3295],{"class":586},[576,3862,3863],{"class":586}," crates\u002Fbuzz-pair-relay\n",[428,3865,3866,3867,3870,3871,3873],{},"Add the following to ",[573,3868,3869],{},"compose.yml"," to start the ",[573,3872,3838],{}," service:",[567,3875,3877],{"className":1052,"code":3876,"language":1054,"meta":423,"style":423},"  pair:\n    image: ${BUZZ_IMAGE:-ghcr.io\u002Fblock\u002Fbuzz:main}\n    entrypoint: [\"\u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-pair-relay\"]\n    environment:\n      BUZZ_PAIR_RELAY_BIND_ADDR: 0.0.0.0:5000\n    ports:\n      - \"${BUZZ_PAIR_RELAY_PORT:-5000}:5000\"\n    restart: unless-stopped\n    networks:\n      [buzz-net]\n",[573,3878,3879,3886,3895,3915,3921,3931,3937,3948,3956,3962],{"__ignoreMap":423},[576,3880,3881,3884],{"class":578,"line":579},[576,3882,3883],{"class":1061},"  pair",[576,3885,914],{"class":719},[576,3887,3888,3890,3892],{"class":578,"line":597},[576,3889,1076],{"class":1061},[576,3891,765],{"class":719},[576,3893,3894],{"class":586}," ${BUZZ_IMAGE:-ghcr.io\u002Fblock\u002Fbuzz:main}\n",[576,3896,3897,3900,3902,3905,3907,3910,3912],{"class":578,"line":603},[576,3898,3899],{"class":1061},"    entrypoint",[576,3901,765],{"class":719},[576,3903,3904],{"class":719}," [",[576,3906,1518],{"class":719},[576,3908,3909],{"class":586},"\u002Fusr\u002Flocal\u002Fbin\u002Fbuzz-pair-relay",[576,3911,1518],{"class":719},[576,3913,3914],{"class":719},"]\n",[576,3916,3917,3919],{"class":578,"line":610},[576,3918,1107],{"class":1061},[576,3920,914],{"class":719},[576,3922,3923,3926,3928],{"class":578,"line":620},[576,3924,3925],{"class":1061},"      BUZZ_PAIR_RELAY_BIND_ADDR",[576,3927,765],{"class":719},[576,3929,3930],{"class":586}," 0.0.0.0:5000\n",[576,3932,3933,3935],{"class":578,"line":625},[576,3934,1086],{"class":1061},[576,3936,914],{"class":719},[576,3938,3939,3941,3943,3946],{"class":578,"line":631},[576,3940,1093],{"class":719},[576,3942,1096],{"class":719},[576,3944,3945],{"class":586},"${BUZZ_PAIR_RELAY_PORT:-5000}:5000",[576,3947,1102],{"class":719},[576,3949,3950,3952,3954],{"class":578,"line":772},[576,3951,1175],{"class":1061},[576,3953,765],{"class":719},[576,3955,1180],{"class":586},[576,3957,3958,3960],{"class":578,"line":1124},[576,3959,2884],{"class":1061},[576,3961,914],{"class":719},[576,3963,3964,3967,3970],{"class":578,"line":1132},[576,3965,3966],{"class":719},"      [",[576,3968,3969],{"class":586},"buzz-net",[576,3971,3914],{"class":719},[428,3973,1002,3974,463,3977,2586,3980,3982],{},[573,3975,3976],{},"BUZZ_PAIRING_RELAY_URL",[573,3978,3979],{},"BUZZ_PAIR_RELAY_PORT",[573,3981,647],{}," file:",[567,3984,3987],{"className":3985,"code":3986,"language":2486},[2484],"BUZZ_PAIRING_RELAY_URL=wss:\u002F\u002Fbuzz.pafor.me\u002Fpair\nBUZZ_PAIR_RELAY_PORT=5000\n",[573,3988,3986],{"__ignoreMap":423},[428,3990,3991,3992,3995],{},"Head to the '",[461,3993,3994],{},"Mobile","' in the Buzz desktop Settings:",[428,3997,3998],{},[432,3999],{"alt":4000,"src":4001},"Settings dialog in Buzz app showing the Mobile devices configuration tab","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-settings-mobile-tab.webp",[428,4003,4004],{},"Click \"Start pairing\" — a QR code is generated; scan this QR code with the Buzz app on the mobile device. It will be paired after you click \"Code Match\".",[428,4006,4007],{},[432,4008],{"alt":4009,"src":4010},"Generating secure pairing QR code in desktop client for Buzz mobile synchronization","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-desktop-client-pairing-qr-code.webp",[428,4012,4013],{},"The agents on the Buzz mobile app are available only if they are running on the Buzz desktop app. The desktop machine has to be running for the agents to work.",[428,4015,4016],{},[432,4017],{"alt":4018,"src":4019},"Buzz mobile application interface showcasing synced active AI companion agents","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSelf-Hosting%20Buzz%20As%20The%20Workspace%20Where%20AI%20Agents%20Become%20Colleagues\u002Fbuzz-mobile-app-active-agents.webp",[491,4021,4023],{"id":4022},"final-thought","Final Thought",[428,4025,4026],{},"While Buzz is still too early for large scale production environments with several bugs and UI limitations, it is an exciting experience for small teams and solo developers. It offers a preview of what a collaborative, AI-first workspace truly feels like.",[491,4028,4030],{"id":4029},"reference","Reference",[501,4032,4033,4040,4047,4054],{},[504,4034,4035],{},[441,4036,4039],{"href":4037,"rel":4038},"https:\u002F\u002Fgithub.com\u002Fblock\u002Fbuzz",[445],"Buzz releases",[504,4041,4042],{},[441,4043,4046],{"href":4044,"rel":4045},"https:\u002F\u002Fblock.xyz\u002Finside\u002Fintroducing-buzz-where-humans-and-agents-work-together",[445],"Introducing Buzz",[504,4048,4049],{},[441,4050,4053],{"href":4051,"rel":4052},"https:\u002F\u002Fwww.hostinger.com\u002Ftutorials\u002Fwhat-is-buzz",[445],"What is buzz",[504,4055,4056],{},[441,4057,4060],{"href":4058,"rel":4059},"https:\u002F\u002Fmiget.com\u002Fblog\u002Fhow-to-self-host-buzz",[445],"How to self-host Buzz (Miget)",[1891,4062,4063],{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}",{"title":423,"searchDepth":597,"depth":603,"links":4065},[4066,4067,4068,4082,4091,4092,4093],{"id":1964,"depth":597,"text":1965},{"id":2009,"depth":597,"text":2010},{"id":2057,"depth":597,"text":2058,"children":4069},[4070,4071,4075,4076,4077,4081],{"id":2061,"depth":603,"text":2062},{"id":2087,"depth":603,"text":2088,"children":4072},[4073,4074],{"id":2091,"depth":610,"text":2092},{"id":2193,"depth":610,"text":2194},{"id":2210,"depth":603,"text":2211},{"id":2427,"depth":603,"text":2428},{"id":2572,"depth":603,"text":2573,"children":4078},[4079,4080],{"id":2576,"depth":610,"text":2577},{"id":2961,"depth":610,"text":2962},{"id":3024,"depth":603,"text":3025},{"id":3064,"depth":597,"text":3065,"children":4083},[4084,4085,4086],{"id":3147,"depth":603,"text":3148},{"id":3192,"depth":603,"text":3193},{"id":3229,"depth":603,"text":3230,"children":4087},[4088,4089,4090],{"id":3253,"depth":610,"text":3254},{"id":3499,"depth":610,"text":3500},{"id":3573,"depth":610,"text":3574},{"id":3831,"depth":597,"text":3832},{"id":4022,"depth":597,"text":4023},{"id":4029,"depth":597,"text":4030},[4095,4096,3484],"collaboration","ai-agents","2026-09-08","Learn how to self-host Block's Buzz on a Linux VPS behind Cloudflare DNS. Run a secure, Nostr-powered workspace where humans and AI agents collaborate.","A premium 16:9 technology card with deep blue and orange accents illustrating how to self-host Block's Buzz relay on an Ubuntu VPS, featuring a clean glassmorphic panel with centered typography.",{"schemaOrg":4101,"robots":1929,"sitemap":4122},[4102,4104],{"@type":4103,"headline":382,"description":4098,"image":696},"TechArticle",{"@type":1928,"name":382,"description":4098,"image":696,"step":4105},[4106,4110,4113,4116,4119],{"@type":4107,"name":4108,"text":4109},"HowToStep","Phase 1: Cloudflare Setup","Create a Cloudflare API Token and configure DNS settings.",{"@type":4107,"name":4111,"text":4112},"Phase 2: Install Docker","Set up and install Docker Engine on Ubuntu VPS.",{"@type":4107,"name":4114,"text":4115},"Phase 3: Clone and Configure","Clone the repository and configure compose variables.",{"@type":4107,"name":4117,"text":4118},"Phase 4: Caddy Integration","Build custom Caddy with Cloudflare DNS challenge module.",{"@type":4107,"name":4120,"text":4121},"Phase 5: Automated Backup","Configure a cron job to automatically back up PostgreSQL.",{"lastmod":4123},"2026-09-03",{"title":4125,"description":4098,"ogTitle":382,"ogDescription":4098,"twitterTitle":382,"twitterDescription":4098},"How to Self-Host Block's Buzz Relay on Ubuntu VPS",[4127,4128,1960,4129,4130],"Nostr","Docker","Caddy","Cloudflare","ir8b59r6ypIp92KOOIJHFgPU_UhHH0zic0M1up4soME",{"id":4133,"title":362,"author":423,"body":4134,"category":5002,"date":5004,"description":485,"extension":1920,"image":486,"imageAlt":487,"isPublished":737,"meta":5005,"minRead":772,"navigation":737,"path":363,"seo":5039,"stem":364,"tags":5041,"updatedAt":5038,"__hash__":5044},"article\u002Fen\u002Farticle\u002Fexposing-hermes-agent-to-private-network-using-cloudflare-warp.md",{"type":425,"value":4135,"toc":4984},[4136,4150,4159,4163,4166,4178,4182,4190,4194,4198,4247,4251,4381,4385,4418,4422,4425,4489,4492,4528,4531,4558,4562,4572,4576,4614,4702,4706,4711,4728,4737,4807,4812,4857,4861,4906,4920,4924,4967,4971,4981],[428,4137,4138,4139,4142,4143,4146,4147,4149],{},"A common challenge arises when you want to access your ",[461,4140,4141],{},"Hermes Agent"," from other devices such as laptops, tablets, or phones without exposing it to the public internet. Utilizing ",[461,4144,4145],{},"Cloudflare WARP"," with ",[461,4148,475],{}," allows you to expose the Hermes Agent globally without opening a single inbound port on your firewall.",[428,4151,4152,4153,4155,4156,4158],{},"If you followed our previous guide, '",[441,4154,374],{"href":375},"', a Hermes Agent is already up and running 24\u002F7. Instead of dealing with the overhead of traditional VPNs, we will use the ",[461,4157,4145],{}," client to expose the Hermes Agent to a private network over the internet.",[491,4160,4162],{"id":4161},"understanding-the-architecture","Understanding the Architecture",[428,4164,4165],{},"The components at play:",[2094,4167,4168,4173],{},[504,4169,4170,4172],{},[461,4171,475],{},": The dashboard at Cloudflare where you define routing rules and access policies.",[504,4174,4175,4177],{},[461,4176,4145],{},": The client application installed on your devices (VPS, laptops, phones). It intercepts traffic destined for your private network and routes it securely.",[536,4179,4181],{"id":4180},"prerequisites","Prerequisites",[501,4183,4184,4187],{},[504,4185,4186],{},"A running Hermes Agent on your VPS.",[504,4188,4189],{},"A free Cloudflare account.",[491,4191,4193],{"id":4192},"step-by-step-guide","Step-by-Step Guide",[536,4195,4197],{"id":4196},"step-1-set-up-cloudflare-zero-trust","Step 1: Set Up Cloudflare Zero Trust",[2094,4199,4200,4208,4215,4226,4233,4240],{},[504,4201,4202,4203,692],{},"Log in to your ",[441,4204,4207],{"href":4205,"rel":4206},"https:\u002F\u002Fdash.cloudflare.com\u002F",[445],"Cloudflare Dashboard",[504,4209,4210,4211],{},"Click on 'Zero Trust' from the left menu.\n",[432,4212],{"alt":4213,"src":4214},"Cloudflare dashboard left sidebar navigation menu with Zero Trust option","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-left-menu.webp",[504,4216,4217,4218,4221,4222],{},"If this is your first time, you will be prompted to choose a plan (the Free tier is perfectly fine for this setup) and name your team (e.g., ",[573,4219,4220],{},"ai-team",").\n",[432,4223],{"alt":4224,"src":4225},"Setting up first-time Cloudflare Zero Trust account and naming the team","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-team-setup.webp",[504,4227,4228,4229],{},"Click on 'Access' then 'Policies' to create an access policy defining who has access to the network.\n",[432,4230],{"alt":4231,"src":4232},"Cloudflare Zero Trust Access Policies page showing newly configured access rules","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-access-policies-page.webp",[504,4234,4235,4236],{},"Click on 'Create new policy'.\n",[432,4237],{"alt":4238,"src":4239},"Cloudflare Access policies page showing no policies added and a button to create a new policy.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20secure%20NodeWarden%20at%20Cloudflare\u002Fcloudflare-access-no-policies-create-button.png",[504,4241,4242,4243],{},"Select 'Emails' and enter your email under 'Policy rules'.\n",[432,4244],{"alt":4245,"src":4246},"Cloudflare Access policy rule configuration screen with an email address specified as the inclusion criteria.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FHow%20to%20secure%20NodeWarden%20at%20Cloudflare\u002Fcloudflare-access-policy-rule-email.png",[536,4248,4250],{"id":4249},"step-2-set-up-cloudflare-warp-client-on-vps","Step 2: Set Up Cloudflare WARP Client on VPS",[2094,4252,4253,4262,4268,4275,4278,4293,4296,4374],{},[504,4254,1560,4255,463,4258,4261],{},[573,4256,4257],{},"sudo apt update",[573,4259,4260],{},"sudo apt install cloudflare-warp"," in the terminal on your VPS.",[504,4263,1560,4264,4267],{},[573,4265,4266],{},"warp-cli registration new \u003CTEAM-NAME>"," in the terminal on your VPS, which will print out a URL.",[504,4269,4270,4271,4274],{},"Copy the printed URL, which will look like ",[573,4272,4273],{},"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fwarp",", and paste it in your browser for authentication.",[504,4276,4277],{},"Since email authentication is used in the policy rule setup above, enter your email to authenticate.",[504,4279,4280,4281,4284,4285,4288,4289,4292],{},"On the '",[461,4282,4283],{},"Success","' page in the browser, right-click and select '",[461,4286,4287],{},"Inspect","' on the blue '",[461,4290,4291],{},"Open Cloudflare WARP","' button.",[504,4294,4295],{},"Copy the long token that is shown in the button's link.",[504,4297,1560,4298,4301,4302,4305,4306],{},[573,4299,4300],{},"warp-cli --accept-tos registration token \"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fauth?token=\u003Ccopied_token>\""," in the terminal on your VPS to connect it to Cloudflare Zero Trust.",[4303,4304],"br",{},"If the 'Error: Failed to communicate with the WARP API' is encounter on Ubuntu 26, run the following commands:",[567,4307,4309],{"className":569,"code":4308,"language":571,"meta":423,"style":423},"sudo systemctl restart warp-svc.service\n\n# Check status\nsudo systemctl status warp-svc.service\n\n# Run the warp-cli registration token again\nwarp-cli --accept-tos registration token   \"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fauth?token=\u003Ccopied_token>\"\n",[573,4310,4311,4323,4327,4332,4343,4347,4352],{"__ignoreMap":423},[576,4312,4313,4315,4317,4320],{"class":578,"line":579},[576,4314,1307],{"class":582},[576,4316,1748],{"class":586},[576,4318,4319],{"class":586}," restart",[576,4321,4322],{"class":586}," warp-svc.service\n",[576,4324,4325],{"class":578,"line":597},[576,4326,738],{"emptyLinePlaceholder":737},[576,4328,4329],{"class":578,"line":603},[576,4330,4331],{"class":606},"# Check status\n",[576,4333,4334,4336,4338,4341],{"class":578,"line":610},[576,4335,1307],{"class":582},[576,4337,1748],{"class":586},[576,4339,4340],{"class":586}," status",[576,4342,4322],{"class":586},[576,4344,4345],{"class":578,"line":620},[576,4346,738],{"emptyLinePlaceholder":737},[576,4348,4349],{"class":578,"line":625},[576,4350,4351],{"class":606},"# Run the warp-cli registration token again\n",[576,4353,4354,4357,4360,4363,4366,4369,4372],{"class":578,"line":631},[576,4355,4356],{"class":582},"warp-cli",[576,4358,4359],{"class":586}," --accept-tos",[576,4361,4362],{"class":586}," registration",[576,4364,4365],{"class":586}," token",[576,4367,4368],{"class":719},"   \"",[576,4370,4371],{"class":586},"https:\u002F\u002F\u003Cteam>.cloudflareaccess.com\u002Fauth?token=\u003Ccopied_token>",[576,4373,1102],{"class":719},[504,4375,4376,4377],{},"Head back to the Cloudflare Zero Trust dashboard, and click on 'Devices'. Your VPS device should now be displayed.\n",[432,4378],{"alt":4379,"src":4380},"Zero Trust Devices dashboard confirming the Linux VPS is connected","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-devices-vps-connected.webp",[536,4382,4384],{"id":4383},"step-3-set-up-traffic-routing","Step 3: Set Up Traffic Routing",[2094,4386,4387,4394,4401,4408],{},[504,4388,4389,4390],{},"Click the profile for your VPS on the Devices dashboard.\n",[432,4391],{"alt":4392,"src":4393},"Accessing details and split tunnel settings for the registered VPS device","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-device-profile.webp",[504,4395,4396,4397],{},"Scroll down to the 'Split Tunnels' section.\n",[432,4398],{"alt":4399,"src":4400},"Split Tunnels section under VPS profile settings","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-split-tunnels-section.webp",[504,4402,4403,4404],{},"Click the 'Manage' button and configure the settings as shown below. Replace the IP address if necessary.\n",[432,4405],{"alt":4406,"src":4407},"Managing Split Tunnels IP and hostname exclusions in Cloudflare settings","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-zero-trust-manage-split-tunnels.webp",[504,4409,4410,4411,463,4414,4417],{},"Exposing the ",[573,4412,4413],{},"address",[573,4415,4416],{},"host"," will route traffic to your services over the same private network.",[536,4419,4421],{"id":4420},"step-4-configure-firewall-on-the-vps","Step 4: Configure Firewall on the VPS",[428,4423,4424],{},"Enable the firewall to allow the '100.96.0.0\u002F12' subnet only, blocking all other public incoming access.",[567,4426,4428],{"className":569,"code":4427,"language":571,"meta":423,"style":423},"sudo ufw enable \nsudo ufw default allow outgoing \nsudo ufw default deny incoming\nsudo ufw allow in from 100.96.0.0\u002F12\n",[573,4429,4430,4441,4458,4472],{"__ignoreMap":423},[576,4431,4432,4434,4437,4439],{"class":578,"line":579},[576,4433,1307],{"class":582},[576,4435,4436],{"class":586}," ufw",[576,4438,1761],{"class":586},[576,4440,1331],{"class":593},[576,4442,4443,4445,4447,4450,4453,4456],{"class":578,"line":597},[576,4444,1307],{"class":582},[576,4446,4436],{"class":586},[576,4448,4449],{"class":586}," default",[576,4451,4452],{"class":586}," allow",[576,4454,4455],{"class":586}," outgoing",[576,4457,1331],{"class":593},[576,4459,4460,4462,4464,4466,4469],{"class":578,"line":603},[576,4461,1307],{"class":582},[576,4463,4436],{"class":586},[576,4465,4449],{"class":586},[576,4467,4468],{"class":586}," deny",[576,4470,4471],{"class":586}," incoming\n",[576,4473,4474,4476,4478,4480,4483,4486],{"class":578,"line":610},[576,4475,1307],{"class":582},[576,4477,4436],{"class":586},[576,4479,4452],{"class":586},[576,4481,4482],{"class":586}," in",[576,4484,4485],{"class":586}," from",[576,4487,4488],{"class":586}," 100.96.0.0\u002F12\n",[428,4490,4491],{},"Allow loopback traffic to avoid breaking local services:",[567,4493,4495],{"className":569,"code":4494,"language":571,"meta":423,"style":423},"sudo ufw allow in on lo\nsudo ufw allow out on lo\n",[573,4496,4497,4513],{"__ignoreMap":423},[576,4498,4499,4501,4503,4505,4507,4510],{"class":578,"line":579},[576,4500,1307],{"class":582},[576,4502,4436],{"class":586},[576,4504,4452],{"class":586},[576,4506,4482],{"class":586},[576,4508,4509],{"class":586}," on",[576,4511,4512],{"class":586}," lo\n",[576,4514,4515,4517,4519,4521,4524,4526],{"class":578,"line":597},[576,4516,1307],{"class":582},[576,4518,4436],{"class":586},[576,4520,4452],{"class":586},[576,4522,4523],{"class":586}," out",[576,4525,4509],{"class":586},[576,4527,4512],{"class":586},[428,4529,4530],{},"Reload the firewall and verify status:",[567,4532,4534],{"className":569,"code":4533,"language":571,"meta":423,"style":423},"sudo ufw reload \nsudo ufw status verbose\n",[573,4535,4536,4547],{"__ignoreMap":423},[576,4537,4538,4540,4542,4545],{"class":578,"line":579},[576,4539,1307],{"class":582},[576,4541,4436],{"class":586},[576,4543,4544],{"class":586}," reload",[576,4546,1331],{"class":593},[576,4548,4549,4551,4553,4555],{"class":578,"line":597},[576,4550,1307],{"class":582},[576,4552,4436],{"class":586},[576,4554,4340],{"class":586},[576,4556,4557],{"class":586}," verbose\n",[536,4559,4561],{"id":4560},"step-5-expose-hermes-agent-to-the-private-network","Step 5: Expose Hermes Agent to the Private Network",[428,4563,4564,4565,4568,4569,692],{},"We will expose the ",[461,4566,4567],{},"Hermes Agent Web Dashboard"," to our private network and use the default authentication provider, ",[461,4570,4571],{},"Nous Research",[541,4573,4575],{"id":4574},"set-up-the-auth-provider","Set Up the Auth Provider",[2094,4577,4578,4587,4594,4601,4608],{},[504,4579,4580,4581,4586],{},"Head to ",[441,4582,4585],{"href":4583,"rel":4584},"https:\u002F\u002Fportal.nousresearch.com",[445],"portal.nousresearch.com"," to register an account.",[504,4588,4589,4590],{},"Select 'Local Dashboards'.\n",[432,4591],{"alt":4592,"src":4593},"Selecting Local Dashboards option in the Nous Research portal","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fnous-portal-local-dashboards-selection.webp",[504,4595,4596,4597],{},"Click 'Register Dashboard'.\n",[432,4598],{"alt":4599,"src":4600},"Clicking Register Dashboard button to create a new dashboard entry","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fnous-portal-register-dashboard.webp",[504,4602,4603,4604],{},"Enter the private network IP address of your VPS as the 'Dashboard redirect URI' and click 'Save'.\n",[432,4605],{"alt":4606,"src":4607},"Registering the private network VPS IP address as redirect URI in Nous Research portal","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fnous-portal-register-redirect-uri.webp",[504,4609,4610,4611,3982],{},"Copy the 'OAuth client ID' and paste it in your ",[573,4612,4613],{},"config.yaml",[567,4615,4619],{"className":4616,"code":4617,"language":4618,"meta":423,"style":423},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","dashboard:\n  theme: default\n  show_token_analytics: false\n  oauth:\n    client_id: agent:cmq02x7ha0002jk0ba3kfnb\n    portal_url: https:\u002F\u002Fportal.nousresearch.com\n  basic_auth:\n    username: ''\n    password_hash: ''\n","yaml",[573,4620,4621,4628,4638,4649,4656,4666,4676,4683,4693],{"__ignoreMap":423},[576,4622,4623,4626],{"class":578,"line":579},[576,4624,4625],{"class":1061},"dashboard",[576,4627,914],{"class":719},[576,4629,4630,4633,4635],{"class":578,"line":597},[576,4631,4632],{"class":1061},"  theme",[576,4634,765],{"class":719},[576,4636,4637],{"class":586}," default\n",[576,4639,4640,4643,4645],{"class":578,"line":603},[576,4641,4642],{"class":1061},"  show_token_analytics",[576,4644,765],{"class":719},[576,4646,4648],{"class":4647},"sfNiH"," false\n",[576,4650,4651,4654],{"class":578,"line":610},[576,4652,4653],{"class":1061},"  oauth",[576,4655,914],{"class":719},[576,4657,4658,4661,4663],{"class":578,"line":620},[576,4659,4660],{"class":1061},"    client_id",[576,4662,765],{"class":719},[576,4664,4665],{"class":586}," agent:cmq02x7ha0002jk0ba3kfnb\n",[576,4667,4668,4671,4673],{"class":578,"line":625},[576,4669,4670],{"class":1061},"    portal_url",[576,4672,765],{"class":719},[576,4674,4675],{"class":586}," https:\u002F\u002Fportal.nousresearch.com\n",[576,4677,4678,4681],{"class":578,"line":631},[576,4679,4680],{"class":1061},"  basic_auth",[576,4682,914],{"class":719},[576,4684,4685,4688,4690],{"class":578,"line":772},[576,4686,4687],{"class":1061},"    username",[576,4689,765],{"class":719},[576,4691,4692],{"class":719}," ''\n",[576,4694,4695,4698,4700],{"class":578,"line":1124},[576,4696,4697],{"class":1061},"    password_hash",[576,4699,765],{"class":719},[576,4701,4692],{"class":719},[541,4703,4705],{"id":4704},"set-up-systemd-to-autostart-the-hermes-dashboard","Set Up Systemd to Autostart the Hermes Dashboard",[2094,4707,4708],{},[504,4709,4710],{},"Create a service file:",[567,4712,4716],{"className":4713,"code":4714,"language":4715,"meta":423,"style":423},"language-shell shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","sudo nano \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhermes-dashboard.service\n","shell",[573,4717,4718],{"__ignoreMap":423},[576,4719,4720,4722,4725],{"class":578,"line":579},[576,4721,1307],{"class":582},[576,4723,4724],{"class":586}," nano",[576,4726,4727],{"class":586}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fhermes-dashboard.service\n",[2094,4729,4730],{"start":597},[504,4731,4732,4733,4736],{},"Paste the following configuration, ensuring ",[573,4734,4735],{},"--host 0.0.0.0"," is part of the command:",[567,4738,4742],{"className":4739,"code":4740,"language":4741,"meta":423,"style":423},"language-ini shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[Unit]\nDescription=Hermes Dashboard\nAfter=network.target\n\n[Service]\nUser=hermes\nWorkingDirectory=\u002Fhome\u002Fhermes\nExecStart=\u002Fhome\u002Fhermes\u002F.local\u002Fbin\u002Fhermes dashboard --host 0.0.0.0\nRestart=always\nRestartSec=10\nEnvironment=PATH=\u002Fhome\u002Fhermes\u002F.local\u002Fbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin:\u002Fbin\n\n[Install]\nWantedBy=multi-user.target\n","ini",[573,4743,4744,4748,4753,4758,4762,4766,4771,4776,4781,4785,4790,4795,4799,4803],{"__ignoreMap":423},[576,4745,4746],{"class":578,"line":579},[576,4747,1656],{},[576,4749,4750],{"class":578,"line":597},[576,4751,4752],{},"Description=Hermes Dashboard\n",[576,4754,4755],{"class":578,"line":603},[576,4756,4757],{},"After=network.target\n",[576,4759,4760],{"class":578,"line":610},[576,4761,738],{"emptyLinePlaceholder":737},[576,4763,4764],{"class":578,"line":620},[576,4765,1680],{},[576,4767,4768],{"class":578,"line":625},[576,4769,4770],{},"User=hermes\n",[576,4772,4773],{"class":578,"line":631},[576,4774,4775],{},"WorkingDirectory=\u002Fhome\u002Fhermes\n",[576,4777,4778],{"class":578,"line":772},[576,4779,4780],{},"ExecStart=\u002Fhome\u002Fhermes\u002F.local\u002Fbin\u002Fhermes dashboard --host 0.0.0.0\n",[576,4782,4783],{"class":578,"line":1124},[576,4784,1715],{},[576,4786,4787],{"class":578,"line":1132},[576,4788,4789],{},"RestartSec=10\n",[576,4791,4792],{"class":578,"line":1140},[576,4793,4794],{},"Environment=PATH=\u002Fhome\u002Fhermes\u002F.local\u002Fbin:\u002Fusr\u002Flocal\u002Fbin:\u002Fusr\u002Fbin:\u002Fbin\n",[576,4796,4797],{"class":578,"line":1148},[576,4798,738],{"emptyLinePlaceholder":737},[576,4800,4801],{"class":578,"line":1156},[576,4802,1729],{},[576,4804,4805],{"class":578,"line":1164},[576,4806,1734],{},[2094,4808,4809],{"start":603},[504,4810,4811],{},"Enable and start the service:",[567,4813,4815],{"className":4713,"code":4814,"language":4715,"meta":423,"style":423},"sudo systemctl daemon-reload\nsudo systemctl enable hermes-dashboard\nsudo systemctl start hermes-dashboard\nsudo systemctl status hermes-dashboard\n",[573,4816,4817,4825,4836,4847],{"__ignoreMap":423},[576,4818,4819,4821,4823],{"class":578,"line":579},[576,4820,1307],{"class":582},[576,4822,1748],{"class":586},[576,4824,1751],{"class":586},[576,4826,4827,4829,4831,4833],{"class":578,"line":597},[576,4828,1307],{"class":582},[576,4830,1748],{"class":586},[576,4832,1761],{"class":586},[576,4834,4835],{"class":586}," hermes-dashboard\n",[576,4837,4838,4840,4842,4845],{"class":578,"line":603},[576,4839,1307],{"class":582},[576,4841,1748],{"class":586},[576,4843,4844],{"class":586}," start",[576,4846,4835],{"class":586},[576,4848,4849,4851,4853,4855],{"class":578,"line":610},[576,4850,1307],{"class":582},[576,4852,1748],{"class":586},[576,4854,4340],{"class":586},[576,4856,4835],{"class":586},[536,4858,4860],{"id":4859},"step-6-install-cloudflare-warp-client-on-desktop","Step 6: Install Cloudflare WARP Client on Desktop",[2094,4862,4863,4871,4874,4881,4888,4895],{},[504,4864,4865,4866,692],{},"Download the Cloudflare WARP client from ",[441,4867,4870],{"href":4868,"rel":4869},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fwarp-client\u002Fget-started\u002F",[445],"Cloudflare's portal",[504,4872,4873],{},"Open and launch the Cloudflare WARP client after installation.",[504,4875,4876,4877],{},"Log in when prompted.\n",[432,4878],{"alt":4879,"src":4880},"Cloudflare WARP client login prompt on desktop machine","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-warp-desktop-login-prompt.webp",[504,4882,4883,4884],{},"A 'Success' page will be displayed after a successful login.\n",[432,4885],{"alt":4886,"src":4887},"Authentication success webpage after logging in to Cloudflare Zero Trust on desktop","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-warp-desktop-login-success.webp",[504,4889,4890,4891],{},"The WARP client should now show it is connected to your Zero Trust team.\n",[432,4892],{"alt":4893,"src":4894},"Desktop Cloudflare WARP client confirming active connection to Zero Trust private network","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-warp-desktop-client-connected.webp",[504,4896,4897,4898,4901,4902],{},"Navigate to your web browser and enter your private IP (e.g., ",[573,4899,4900],{},"100.96.0.3","). The Hermes Web Dashboard should load successfully.\n",[432,4903],{"alt":4904,"src":4905},"Accessing the private Hermes Agent Web Dashboard in browser on desktop","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fhermes-agent-dashboard-desktop-view.webp",[4907,4908,4909],"blockquote",{},[428,4910,4911,4914,4915,4919],{},[461,4912,4913],{},"Pro Tip for macOS Users:"," If you are using the WARP client to access multiple Cloudflare accounts, check out our quick guide on ",[461,4916,4917],{},[441,4918,398],{"href":399}," to make switching between accounts seamless.",[536,4921,4923],{"id":4922},"step-7-install-cloudflare-warp-client-on-ios-devices","Step 7: Install Cloudflare WARP Client on iOS Devices",[2094,4925,4926,4932,4940,4948,4956],{},[504,4927,3577,4928,4931],{},[461,4929,4930],{},"Cloudflare One"," from the App Store.",[504,4933,4934,4935],{},"Open the Cloudflare One app and enter your team name when prompted.\n",[432,4936],{"alt":4937,"src":4938,"width":4939},"Entering Cloudflare Zero Trust team name in Cloudflare One app on iOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-one-ios-team-name-prompt.webp",239,[504,4941,4942,4943],{},"Log in using the same email address that was configured in the policy rule above.\n",[432,4944],{"alt":4945,"src":4946,"width":4947},"Email authentication prompt for Cloudflare Zero Trust on iOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-one-ios-email-login.webp",229,[504,4949,4950,4951],{},"Once it is connected, it should look like the following:\n",[432,4952],{"alt":4953,"src":4954,"width":4955},"Cloudflare One app showing connected status on iOS mobile device","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fcloudflare-one-ios-client-connected.webp",322,[504,4957,4958,4959,4961,4962],{},"Navigate to your web browser and enter the private IP ",[573,4960,4900],{}," to access the Hermes Web Dashboard on your mobile device.\n",[432,4963],{"alt":4964,"src":4965,"width":4966},"Accessing Hermes Agent Web Dashboard interface on mobile phone browser","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FExposing%20Hermes%20Agent%20to%20Private%20Network%20Using%20Cloudflare%20WARP\u002Fhermes-agent-dashboard-mobile-view.webp",345,[491,4968,4970],{"id":4969},"conclusion","Conclusion",[428,4972,4973,4974,4976,4977,4980],{},"With ",[461,4975,475],{}," handling identity policies and the ",[461,4978,4979],{},"WARP"," client routing traffic over an encrypted tunnel, your Hermes Agent is securely reachable from your devices globally. This setup lays a secure, robust foundation for building and accessing a fully remote, private AI infrastructure.",[1891,4982,4983],{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":423,"searchDepth":597,"depth":603,"links":4985},[4986,4989,5001],{"id":4161,"depth":597,"text":4162,"children":4987},[4988],{"id":4180,"depth":603,"text":4181},{"id":4192,"depth":597,"text":4193,"children":4990},[4991,4992,4993,4994,4995,4999,5000],{"id":4196,"depth":603,"text":4197},{"id":4249,"depth":603,"text":4250},{"id":4383,"depth":603,"text":4384},{"id":4420,"depth":603,"text":4421},{"id":4560,"depth":603,"text":4561,"children":4996},[4997,4998],{"id":4574,"depth":610,"text":4575},{"id":4704,"depth":610,"text":4705},{"id":4859,"depth":603,"text":4860},{"id":4922,"depth":603,"text":4923},{"id":4969,"depth":597,"text":4970},[4096,5003],"security","2026-07-09",{"schemaOrg":5006,"robots":1929,"sitemap":5037},[5007],{"@type":1928,"headline":362,"description":485,"name":362,"image":486,"step":5008},[5009,5013,5017,5021,5025,5029,5033],{"@type":4107,"name":5010,"text":5011,"url":5012,"image":4214},"Set Up Cloudflare Zero Trust","Log in to your Cloudflare Dashboard. Click on 'Zero Trust' from the left menu. If this is your first time, you will be prompted to choose a plan (the Free tier is perfectly fine for this setup) and name your team (e.g., ai-team). Click on 'Access' th","#step-1",{"@type":4107,"name":5014,"text":5015,"url":5016,"image":4380},"Set Up Cloudflare WARP Client on VPS","Run sudo apt update and sudo apt install cloudflare-warp in the terminal on your VPS. Run warp-cli registration new \u003CTEAM-NAME> in the terminal on your VPS, which will print out a URL. Copy the printed URL, which will look like https:\u002F\u002F\u003Cteam>.cloudfl","#step-2",{"@type":4107,"name":5018,"text":5019,"url":5020,"image":4393},"Set Up Traffic Routing","Click the profile for your VPS on the Devices dashboard. Scroll down to the 'Split Tunnels' section. Click the 'Manage' button and configure the settings as shown below. Replace the IP address if necessary. Exposing the address and host will route tr","#step-3",{"@type":4107,"name":5022,"text":5023,"url":5024},"Configure Firewall on the VPS","Enable the firewall to allow the '100.96.0.0\u002F12' subnet only, blocking all other public incoming access. bash Allow loopback traffic to avoid breaking local services: bash Reload the firewall and verify status: bash","#step-4",{"@type":4107,"name":5026,"text":5027,"url":5028},"Expose Hermes Agent to the Private Network","We will expose the Hermes Agent Web Dashboard to our private network and use the default authentication provider, Nous Research.","#step-5",{"@type":4107,"name":5030,"text":5031,"url":5032,"image":4880},"Install Cloudflare WARP Client on Desktop","Download the Cloudflare WARP client from Cloudflare's portal. Open and launch the Cloudflare WARP client after installation. Log in when prompted. A 'Success' page will be displayed after a successful login. The WARP client should now show it is conn","#step-6",{"@type":4107,"name":5034,"text":5035,"url":5036,"image":4938},"Install Cloudflare WARP Client on iOS Devices","Install Cloudflare One from the App Store. Open the Cloudflare One app and enter your team name when prompted. Log in using the same email address that was configured in the policy rule above. Once it is connected, it should look like the following:","#step-7",{"lastmod":5038},"2026-09-28",{"title":5040,"description":485,"ogTitle":362,"ogDescription":485,"twitterTitle":362,"twitterDescription":485},"Secure Hermes Agent Access with Cloudflare Zero Trust",[4145,1938,4141,5042,5043],"VPN","Tutorial","7w7yHDwhXSX7-e5xSvZ3rQ_6OcpB47010zvSqV1GJ9M",[5046,5047,5842],{"id":4133,"title":362,"author":423,"body":4134,"category":5002,"date":5004,"description":485,"extension":1920,"image":486,"imageAlt":487,"isPublished":737,"meta":5005,"minRead":772,"navigation":737,"path":363,"seo":5039,"stem":364,"tags":5041,"updatedAt":5038,"__hash__":5044},{"id":5048,"title":414,"author":1939,"body":5049,"category":5826,"date":5828,"description":5829,"extension":1920,"image":5830,"imageAlt":5831,"isPublished":737,"meta":5832,"minRead":631,"navigation":737,"path":415,"seo":5837,"stem":416,"tags":5838,"updatedAt":1939,"__hash__":5841},"article\u002Fen\u002Farticle\u002Fuse-cloudflare-as-ai-memory.md",{"type":425,"value":5050,"toc":5808},[5051,5055,5058,5061,5065,5068,5082,5086,5093,5106,5109,5112,5153,5157,5239,5243,5269,5378,5389,5393,5398,5439,5463,5467,5472,5543,5548,5552,5586,5592,5631,5635,5667,5671,5679,5683,5713,5717,5757,5759,5762,5765,5768,5771,5805],[491,5052,5054],{"id":5053},"the-importance-of-persistent-ai-memory-for-agents","The Importance of Persistent AI Memory for Agents",[428,5056,5057],{},"As AI assistants become integrated into our daily lives, we frequently encounter the blank context issue. The decisions made last week are forgotten, requiring us to input the same tech stack details, and set the user preferences all over again.",[428,5059,5060],{},"Instead of starting from scratch every time, we need to build a memory system that evolves, continuously understands a user's decisions and eliminates the need to repeat context.",[491,5062,5064],{"id":5063},"self-hosted-vs-built-in-ai-memory-systems","Self-Hosted vs. Built-In AI Memory Systems",[428,5066,5067],{},"Many AI agents come with built-in memory, but we don't just use one agent for all purposes. We use Claude for architecting and designing a project; Kimi for coding; and ChatGPT for research. The context is not shared among these agents; it remains siloed per agent.",[428,5069,5070,5071,5076,5077,5081],{},"From a software engineering point of view, we don't trust black boxes. We need AI memory system that is observable, auditable, and under our control. The open sourced project, ",[441,5072,5075],{"href":5073,"rel":5074},"https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fsecond-brain-cloudflare\u002Ftree\u002Fmain",[445],"Second Brain",", forked from ",[441,5078,5079],{"href":5079,"rel":5080},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare",[445],", provides a persistent and self-hosted memory system with Model Context Protocol (MCP) support.  Any compatible AI agents such as Claude, ChatGPT, Kimi Code can share the same context.",[491,5083,5085],{"id":5084},"how-to-build-a-second-brain-ai-memory-on-cloudflare","How to Build a Second Brain AI Memory on Cloudflare",[428,5087,5088,5089,5092],{},"The Second Brain memory system is deployed on ",[461,5090,5091],{},"Cloudflare Workers",", which provides globally distributed, low-latency execution server infrastructure. This allows the memory recall and other operations to execute with minimal latency to the AI’s reasoning loop.",[428,5094,1372,5095,5098,5099,5102,5103,5105],{},[461,5096,5097],{},"Workers AI"," embedding model is used for generating the embeddings. These embeddings are stored in ",[461,5100,5101],{},"Cloudflare Vectorize",", which is a globally distributed vector database. The ",[461,5104,5101],{}," performs the cosine similarity search for semantically related memories.",[428,5107,5108],{},"Duplication detection and smart merging mechanisms are implemented in Second Brain. Content with less than 85% similarity is stored, otherwise it is blocked or marked as a duplicate candidate. Text exceeding 1,600 characters is split at sentence or line-break boundaries with 200-character overlap to prevent loss of context. Then each chunk is embedded as a vector which allows precise matching.",[428,5110,5111],{},"The following tools are exposed as MCP interfaces to be used in AI agents:",[501,5113,5114,5120,5126,5132,5138,5144,5150],{},[504,5115,5116,5119],{},[573,5117,5118],{},"remember",": Store ideas, decisions, preferences, and project context",[504,5121,5122,5125],{},[573,5123,5124],{},"append",": Add an update to an existing memory",[504,5127,5128,5131],{},[573,5129,5130],{},"update",": Replace an existing memory",[504,5133,5134,5137],{},[573,5135,5136],{},"recall",": Find memories by meaning rather than exact wording",[504,5139,5140,5143],{},[573,5141,5142],{},"list_recent",": Browse recently saved memories",[504,5145,5146,5149],{},[573,5147,5148],{},"forget",": Permanently delete a memory",[504,5151,5152],{},"`link\u002Fconnections``: Connect related memories (v2 graph feature)",[536,5154,5156],{"id":5155},"setup-second-brain-on-cloudflare","Setup Second Brain on Cloudflare",[2094,5158,5159,5176,5183,5190,5197,5204,5215,5222,5225,5232],{},[504,5160,2105,5161,5164,5165,5170,5171,5175],{},[573,5162,5163],{},"Deploy to Cloudflare"," at the ",[441,5166,5169],{"href":5167,"rel":5168},"https:\u002F\u002Fgithub.com\u002FTech-Voyage-Dev\u002Fsecond-brain-cloudflare",[445],"Github repo"," page. [[",[432,5172],{"alt":5173,"src":5174},"GitHub page with the Deploy to Cloudflare button highlighted","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fdeploy-to-cloudflare-button.webp","]]",[504,5177,5178,5179],{},"Fill out the Cloudflare Worker form.\n",[432,5180],{"alt":5181,"src":5182},"Cloudflare Workers deployment configuration form","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-deployment-form.webp",[504,5184,5185,5186],{},"Enter '384' for Dimensions; select 'cosine' for Metric; and click the Deploy button.\n",[432,5187],{"alt":5188,"src":5189},"Cloudflare Vectorize database creation settings screen","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-vectorize-configuration.webp",[504,5191,5192,5193],{},"The following is the overview of the Second Brain in Cloudflare Worker\n",[432,5194],{"alt":5195,"src":5196},"Overview dashboard of the deployed Second Brain worker","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-second-brain-overview.webp",[504,5198,5199,5200],{},"Click on 'Settings', then click edit icon for 'AUTH_TOKEN' for creating a token\n",[432,5201],{"alt":5202,"src":5203},"Cloudflare Worker variable settings highlighting AUTH_TOKEN","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-auth-token-settings.webp",[504,5205,5206,5207,5211],{},"Click the 'Rotate' link for entering a new value           ",[432,5208],{"alt":5209,"src":5210},"AUTH_TOKEN variable modification and rotation screen","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-auth-token-rotate.webp",[432,5212],{"alt":5213,"src":5214},"Entering the generated random string into the AUTH_TOKEN value field","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fcloudflare-worker-auth-token-value-input.webp",[504,5216,5217,5218,5221],{},"Run the command ",[573,5219,5220],{},"openssl rand -base64 32"," at macOS terminal to create a random value and paste it in the 'Value' input field.",[504,5223,5224],{},"Click the 'Deploy' button to update the new value of 'AUTH_TOKEN'.",[504,5226,5227,5228],{},"Open the Second Brain worker url on the web browser\n",[432,5229],{"alt":5230,"src":5231},"Second Brain Web UI login screen with Bearer Token input","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fsecond-brain-web-ui-login.webp",[504,5233,5234,5235,5238],{},"Enter the created 'AUTH_TOKEN' in the ",[573,5236,5237],{},"Bearer token"," input field and click 'Connect' button to login to the Web UI.",[536,5240,5242],{"id":5241},"integrating-claude-desktop-via-mcp","Integrating Claude Desktop via MCP",[2094,5244,5245,5252,5259],{},[504,5246,5247,5248],{},"Click on 'Customize' at Claude Desktop.\n",[432,5249],{"alt":5250,"src":5251},"Claude Desktop interface pointing to the Customize button","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-customize-button.webp",[504,5253,5254,5255],{},"Click on 'Developer' to manually edit the MCP Servers config file\n",[432,5256],{"alt":5257,"src":5258},"Claude Desktop Developer settings menu to access MCP config","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-developer-menu.webp",[504,5260,5261,5262,5265,5266],{},"Add the following code to the ",[573,5263,5264],{},"mcpServers"," section in",[573,5267,5268],{},"claude_desktop_config.json",[567,5270,5272],{"className":710,"code":5271,"language":712,"meta":423,"style":423},"    \"second-brain\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"mcp-remote\",\n        \"https:\u002F\u002F\u003Cyour-worker-url>\u002Fmcp\",\n        \"--header\",\n        \"Authorization: Bearer \u003Cyour-token>\"\n      ]\n    }\n",[573,5273,5274,5289,5311,5325,5337,5348,5359,5368,5373],{"__ignoreMap":423},[576,5275,5276,5279,5282,5284,5287],{"class":578,"line":579},[576,5277,5278],{"class":719},"    \"",[576,5280,5281],{"class":586},"second-brain",[576,5283,1518],{"class":719},[576,5285,5286],{"class":593},": ",[576,5288,720],{"class":719},[576,5290,5291,5294,5297,5299,5301,5303,5306,5308],{"class":578,"line":597},[576,5292,5293],{"class":719},"      \"",[576,5295,5296],{"class":2713},"command",[576,5298,1518],{"class":719},[576,5300,765],{"class":719},[576,5302,1096],{"class":719},[576,5304,5305],{"class":586},"npx",[576,5307,1518],{"class":719},[576,5309,5310],{"class":719},",\n",[576,5312,5313,5315,5318,5320,5322],{"class":578,"line":603},[576,5314,5293],{"class":719},[576,5316,5317],{"class":2713},"args",[576,5319,1518],{"class":719},[576,5321,765],{"class":719},[576,5323,5324],{"class":719}," [\n",[576,5326,5327,5330,5333,5335],{"class":578,"line":610},[576,5328,5329],{"class":719},"        \"",[576,5331,5332],{"class":586},"mcp-remote",[576,5334,1518],{"class":719},[576,5336,5310],{"class":719},[576,5338,5339,5341,5344,5346],{"class":578,"line":620},[576,5340,5329],{"class":719},[576,5342,5343],{"class":586},"https:\u002F\u002F\u003Cyour-worker-url>\u002Fmcp",[576,5345,1518],{"class":719},[576,5347,5310],{"class":719},[576,5349,5350,5352,5355,5357],{"class":578,"line":625},[576,5351,5329],{"class":719},[576,5353,5354],{"class":586},"--header",[576,5356,1518],{"class":719},[576,5358,5310],{"class":719},[576,5360,5361,5363,5366],{"class":578,"line":631},[576,5362,5329],{"class":719},[576,5364,5365],{"class":586},"Authorization: Bearer \u003Cyour-token>",[576,5367,1102],{"class":719},[576,5369,5370],{"class":578,"line":772},[576,5371,5372],{"class":719},"      ]\n",[576,5374,5375],{"class":578,"line":1124},[576,5376,5377],{"class":719},"    }\n",[428,5379,5380,5384,5385],{},[432,5381],{"alt":5382,"src":5383},"Claude Desktop MCP configuration JSON containing the Second Brain server","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-mcp-config-json.webp","\n4. Restart Claude Desktop and check the 'Local MCP servers'. The status says 'running'",[432,5386],{"alt":5387,"src":5388},"Claude Desktop displaying running status for the Second Brain MCP server","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-mcp-status-running.webp",[536,5390,5392],{"id":5391},"integrating-claude-code-via-mcp","Integrating Claude Code via MCP",[501,5394,5395],{},[504,5396,5397],{},"Run the following command to add the MCP",[567,5399,5401],{"className":4713,"code":5400,"language":4715,"meta":423,"style":423},"claude mcp add --transport http second-brain https:\u002F\u002F\u003Cyour-worker-url>\u002Fmcp\n",[573,5402,5403],{"__ignoreMap":423},[576,5404,5405,5408,5411,5414,5417,5420,5423,5426,5428,5431,5434,5436],{"class":578,"line":579},[576,5406,5407],{"class":582},"claude",[576,5409,5410],{"class":586}," mcp",[576,5412,5413],{"class":586}," add",[576,5415,5416],{"class":586}," --transport",[576,5418,5419],{"class":586}," http",[576,5421,5422],{"class":586}," second-brain",[576,5424,5425],{"class":586}," https:\u002F\u002F",[576,5427,3427],{"class":719},[576,5429,5430],{"class":586},"your-worker-ur",[576,5432,5433],{"class":593},"l",[576,5435,3436],{"class":719},[576,5437,5438],{"class":586},"\u002Fmcp\n",[501,5440,5441,5447],{},[504,5442,5443,5444],{},"Claude Code detects that the endpoint requires OAuth and will open the login page at the web browser for entering ",[573,5445,5446],{},"AUTH_TOKEN",[504,5448,5449,5450,5453,5454,5457,5458,692],{},"Create the ",[573,5451,5452],{},"CLAUDE.md"," file in ",[573,5455,5456],{},"~\u002F.claude"," folder with the instructions from ",[441,5459,5462],{"href":5460,"rel":5461},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare\u002Fblob\u002Fmain\u002FAI_Instructions\u002FCLAUDE_INSTRUCTIONS.md",[445],"CLAUDE_INSTRUCTIONS.md",[536,5464,5466],{"id":5465},"integrating-gemini-cli-via-mcp","Integrating Gemini CLI via MCP",[2094,5468,5469],{},[504,5470,5471],{},"Add the following MCP server settings to '.\u002F.gemini\u002Fsettings.json'",[567,5473,5475],{"className":710,"code":5474,"language":712,"meta":423,"style":423},"    \"second-brain\": {\n      \"httpUrl\": \"https:\u002F\u002F\u003Cyour-worker-url>\u002Fmcp\",\n      \"oauth\": {\n        \"enabled\": true\n      }\n    }\n",[573,5476,5477,5489,5508,5521,5534,5539],{"__ignoreMap":423},[576,5478,5479,5481,5483,5485,5487],{"class":578,"line":579},[576,5480,5278],{"class":719},[576,5482,5281],{"class":586},[576,5484,1518],{"class":719},[576,5486,5286],{"class":593},[576,5488,720],{"class":719},[576,5490,5491,5493,5496,5498,5500,5502,5504,5506],{"class":578,"line":597},[576,5492,5293],{"class":719},[576,5494,5495],{"class":2713},"httpUrl",[576,5497,1518],{"class":719},[576,5499,765],{"class":719},[576,5501,1096],{"class":719},[576,5503,5343],{"class":586},[576,5505,1518],{"class":719},[576,5507,5310],{"class":719},[576,5509,5510,5512,5515,5517,5519],{"class":578,"line":603},[576,5511,5293],{"class":719},[576,5513,5514],{"class":2713},"oauth",[576,5516,1518],{"class":719},[576,5518,765],{"class":719},[576,5520,752],{"class":719},[576,5522,5523,5525,5528,5530,5532],{"class":578,"line":610},[576,5524,5329],{"class":719},[576,5526,5527],{"class":582},"enabled",[576,5529,1518],{"class":719},[576,5531,765],{"class":719},[576,5533,3652],{"class":719},[576,5535,5536],{"class":578,"line":620},[576,5537,5538],{"class":719},"      }\n",[576,5540,5541],{"class":578,"line":625},[576,5542,5377],{"class":719},[2094,5544,5545],{"start":597},[504,5546,5547],{},"Start the Gemini CLI",[536,5549,5551],{"id":5550},"test-second-brain-in-ai-agents","Test Second Brain in AI Agents",[2094,5553,5554,5565,5579],{},[504,5555,5556,5557,5560,5561],{},"Started with a simple brand palette settings in '",[461,5558,5559],{},"Claude Desktop","', the Second Brain is not called.\n",[432,5562],{"alt":5563,"src":5564},"First test in Claude Desktop without the Second Brain memory layer active","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-first-run-brand-palette.webp",[504,5566,5567,5568,5571,5572,5574,5575],{},"Tried with the keyword, 'remember', only ",[573,5569,5570],{},"memory_user-edits"," tools in '",[461,5573,5559],{},"' are used but not Second Brain.\n",[432,5576],{"alt":5577,"src":5578},"Claude Desktop falling back to local built-in user edits instead of Second Brain","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-remember-built-in-tool-fallback.webp",[504,5580,5581,5582,5585],{},"Tried the the following prompt in '",[461,5583,5584],{},"Claude Code","', Second Brain was called.",[567,5587,5590],{"className":5588,"code":5589,"language":2486},[2484],"Remember Our brand palette uses `#1a1a2e` as primary, `#16213e` as secondary, and `#e94560` as accent. Never use pure black.\"\n",[573,5591,5589],{"__ignoreMap":423},[428,5593,5594,5598,5599,5602,5606,5607,5611,5612,5614,5615,5619,5620,5623,5624,5606,5628],{},[432,5595],{"alt":5596,"src":5597},"Claude Code terminal window showing successful trigger of the Second Brain MCP","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-code-second-brain-mcp-called.webp","\n4. Verified the colour settings in the ",[461,5600,5601],{},"Second Brain at Cloudflare",[432,5603],{"alt":5604,"src":5605},"Verifying the saved brand color codes in the Second Brain database Web UI","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fsecond-brain-web-ui-color-verification.webp","\n- ",[5608,5609,5610],"em",{},"The reason Claude Code worked was because the CLAUDE_INSTRUCTIONS.md contains the 'Second Brain' keywords.","\n5. Included 'Second Brain' as keywords in '",[461,5613,5559],{},"',  need to be explicitly specified to store to and retrieve from the Second Brain memory layer.\n",[432,5616],{"alt":5617,"src":5618},"Triggering Second Brain in Claude Desktop by explicitly mentioning keywords","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fclaude-desktop-second-brain-explicit-trigger.webp","\n6. The keywords, 'Second Brain', need to be mentioned in the ",[461,5621,5622],{},"Gemini CLI"," to trigger the Second Brain MCP.\n",[432,5625],{"alt":5626,"src":5627},"Gemini CLI terminal window demonstrating successful Second Brain MCP calls","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fgemini-cli-second-brain-trigger.webp",[5608,5629,5630],{},"Adding similar instructions to GEMINI.md like what has been done in CLAUDE_INSTRUCTIONS.md will trigger the Second Brain without mentioning the keywords.",[536,5632,5634],{"id":5633},"web-browser-extensions","Web Browser Extensions",[501,5636,5637,5640],{},[504,5638,5639],{},"Extensions are available for Chrome, Firefox and Microsoft Edge web browsers.",[504,5641,5642,5643],{},"The extensions are for\n",[501,5644,5645,5651,5657],{},[504,5646,5647,5650],{},[461,5648,5649],{},"Capture the current page"," — saves the title and URL to the Second Brain",[504,5652,5653,5656],{},[461,5654,5655],{},"Capture highlighted text"," — select any text on a page before clicking capture; the excerpt is saved alongside the title and URL",[504,5658,5659,5662,5663,5666],{},[461,5660,5661],{},"Add a note"," — type context or ",[573,5664,5665],{},"#hashtags"," in the popup before saving; hashtags are automatically extracted as tags",[536,5668,5670],{"id":5669},"syncing-personal-knowledge-with-the-obsidian-plugin","Syncing Personal Knowledge with the Obsidian Plugin",[501,5672,5673,5676],{},[504,5674,5675],{},"Obsidian plugin is available to sync the notes from the Obsidian Vault to Second Brain at Cloudflare.",[504,5677,5678],{},"Notes can be tagged for syncing to the Second Brain",[541,5680,5682],{"id":5681},"install-obsidian-plugin","Install Obsidian Plugin",[2094,5684,5685,5692,5699,5706],{},[504,5686,5687,5688],{},"Open Obsidian → Settings → Community Plugins\n",[432,5689],{"alt":5690,"src":5691},"Obsidian settings panel navigating to the Community Plugins section","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-settings-community-plugins.webp",[504,5693,5694,5695],{},"Click on 'Browse' button\n",[432,5696],{"alt":5697,"src":5698},"Obsidian community plugins search page showing the Browse button","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-community-plugins-browse.webp",[504,5700,5701,5702],{},"Search for 'Second Brain Sync'\n",[432,5703],{"alt":5704,"src":5705},"Searching for Second Brain Sync plugin in Obsidian marketplace","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-community-plugins-search-second-brain.webp",[504,5707,5708,5709],{},"Click 'Install' button then 'Enable' button\n",[432,5710],{"alt":5711,"src":5712},"Installing and enabling the Second Brain Sync plugin in Obsidian","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-plugin-install-and-enable.webp",[541,5714,5716],{"id":5715},"configure-obsidian-plugin","Configure Obsidian Plugin",[2094,5718,5719,5722,5729,5736,5743,5750],{},[504,5720,5721],{},"Open Obsidian → Settings → Second Brain Sync",[504,5723,5724,5725],{},"Enter the 'URL' and 'Auth token'\n",[432,5726],{"alt":5727,"src":5728},"Entering Worker URL and Auth Token in Obsidian plugin settings","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-plugin-configuration-credentials.webp",[504,5730,5731,5732],{},"Click 'Test' button to verify it is connected.\n",[432,5733],{"alt":5734,"src":5735},"Obsidian plugin connection test showing successful verification","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-plugin-connection-test-success.webp",[504,5737,5738,5739],{},"Configure the sync behaviours. Set the 'Sync tag' and enable 'Auto-sync on save'.\n",[432,5740],{"alt":5741,"src":5742},"Configuring Sync Tag and enabling Auto-sync on save in Obsidian","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-plugin-sync-behavior-settings.webp",[504,5744,5745,5746],{},"Create a note in Obsidian with the tag, 'second-brain', as it was configured as the 'Sync tag'.\n",[432,5747],{"alt":5748,"src":5749},"Creating a new Obsidian note tagged with second-brain for synchronization","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fobsidian-note-with-sync-tag.webp",[504,5751,5752,5753],{},"The note has been saved and synced to the Second Brain deployed at Cloudflare.\n",[432,5754],{"alt":5755,"src":5756},"Verifying the successfully synchronized Obsidian note in Second Brain Web UI","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002Fsecond-brain-web-ui-synced-note-verification.webp",[491,5758,4970],{"id":4969},[428,5760,5761],{},"Second Brain provides an open-source solution to one of the most frustrating issues in AI: persistent memory. By combining it with Cloudflare infrastructure, it delivers a fully self-hosted memory layer that is globally distributed with low latency. The MCP tools built into Second Brain make this memory portable across all AI agents.",[428,5763,5764],{},"The Obsidian plugin extends the Second Brain into personal knowledge management. Notes in an Obsidian vault can be selectively synchronised to Second Brain, transforming raw notes into structured context that AI agents can semantically understand and retrieve.",[428,5766,5767],{},"By combining self-hosting, semantic search, and standards-based MCP integration; Second Brain proves to be more than just a memory layer but a practical foundation for building an AI ecosystem.",[491,5769,5770],{"id":4029},"Reference:",[501,5772,5773,5779,5785,5792,5799],{},[504,5774,5775],{},[441,5776,5777],{"href":5777,"rel":5778},"https:\u002F\u002Fwww.thesecondbrain.dev\u002F",[445],[504,5780,5781],{},[441,5782,5783],{"href":5783,"rel":5784},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare\u002Fwiki\u002FHow-It-Works",[445],[504,5786,5787],{},[441,5788,5791],{"href":5789,"rel":5790},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare\u002Fwiki\u002FConnect-to-AI-Clients",[445],"Connect to AI Clients",[504,5793,5794],{},[441,5795,5798],{"href":5796,"rel":5797},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-cloudflare\u002Fwiki\u002FObsidian-Plugin",[445],"Second Brain Obsidian Plugin",[504,5800,5801],{},[441,5802,5803],{"href":5803,"rel":5804},"https:\u002F\u002Fgithub.com\u002Frahilp\u002Fsecond-brain-obsidian-plugin",[445],[1891,5806,5807],{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}",{"title":423,"searchDepth":597,"depth":603,"links":5809},[5810,5811,5812,5824,5825],{"id":5053,"depth":597,"text":5054},{"id":5063,"depth":597,"text":5064},{"id":5084,"depth":597,"text":5085,"children":5813},[5814,5815,5816,5817,5818,5819,5820],{"id":5155,"depth":603,"text":5156},{"id":5241,"depth":603,"text":5242},{"id":5391,"depth":603,"text":5392},{"id":5465,"depth":603,"text":5466},{"id":5550,"depth":603,"text":5551},{"id":5633,"depth":603,"text":5634},{"id":5669,"depth":603,"text":5670,"children":5821},[5822,5823],{"id":5681,"depth":610,"text":5682},{"id":5715,"depth":610,"text":5716},{"id":4969,"depth":597,"text":4970},{"id":4029,"depth":597,"text":5770},[5827,4096],"cloudflare","2026-08-07","Learn how to build a persistent, self-hosted AI memory system on Cloudflare using Second Brain and MCP. Share context across Claude, Gemini, and Obsidian.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FUse%20Cloudflare%20as%20AI%20memory\u002FEN-Use-Cloudflare-as-AI-memory.webp","A personal self-hosted AI memory system deployed on Cloudflare Workers and Vectorize using the Model Context Protocol (MCP) and Obsidian sync.",{"schemaOrg":5833,"robots":1929,"sitemap":5836},[5834],{"@type":4103,"headline":5835,"description":5829},"Build a Self-Hosted AI Memory System with Cloudflare & MCP",{"lastmod":5828},{"title":5835,"description":5829,"ogTitle":414,"ogDescription":5829,"twitterTitle":414,"twitterDescription":5829},[4130,5839,5840,5075,1936],"MCP","AI Memory","i-n5KfCSdIReLHWXO0pss_aKBTXq5lNG61z0LAefVgk",{"id":5843,"title":398,"author":423,"body":5844,"category":6358,"date":6359,"description":6360,"extension":1920,"image":6361,"imageAlt":6362,"isPublished":737,"meta":6363,"minRead":610,"navigation":737,"path":399,"seo":6367,"stem":400,"tags":6368,"updatedAt":1939,"__hash__":6371},"article\u002Fen\u002Farticle\u002Fswitch-between-multiple-cloudflare-warp-orgs-on-mac.md",{"type":425,"value":5845,"toc":6351},[5846,5850,5853,5860,5864,5870,5873,5876,5880,5883,5890,5906,6200,6311,6313,6316,6318,6348],[491,5847,5849],{"id":5848},"what-is-cloudflare-warp","What Is Cloudflare WARP?",[428,5851,5852],{},"Cloudflare WARP is a client-side application that routes specified device traffic through Cloudflare's global network instead of directly out to the public internet.",[428,5854,5855,5856,5859],{},"It creates an encrypted tunnel built on the ",[461,5857,5858],{},"WireGuard"," protocol, securing traffic from the device to the nearest Cloudflare data center. Policies can then be created in your Cloudflare dashboard to filter, log, inspect, or route this incoming traffic.",[491,5861,5863],{"id":5862},"why-do-we-need-cloudflare-warp","Why Do We Need Cloudflare WARP?",[428,5865,5866,5867,692],{},"To securely expose internal resources—such as private web services or SaaS applications—to employees, contractors, and other stakeholders, the Cloudflare WARP client is the as the client-side enforcement point for ",[461,5868,5869],{},"Zero Trust Network Access (ZTNA)",[428,5871,5872],{},"The Cloudflare WARP client is installed on a user’s laptop or phone. It requires users to authenticate and meet specific security posture checks (such as coming from an approved IP range, using a registered email domain, or running an active firewall) before granting access.",[428,5874,5875],{},"By tunneling device traffic directly to Cloudflare, the user's identity, device, and policies are verified before requests ever reach internal resources. As a result, internal resources are never exposed to the public internet, and every single request is fully logged and audited.",[491,5877,5879],{"id":5878},"supporting-multiple-warp-profiles-on-one-device","Supporting Multiple WARP Profiles on One Device",[428,5881,5882],{},"When users need to switch between personal and corporate Cloudflare accounts, or when system administrators manage multiple tenants, supporting multiple WARP profiles on a single device becomes crucial.",[428,5884,5885,5886,5889],{},"To achieve this on macOS, we can use a ",[573,5887,5888],{},".mobileconfig"," MDM profile file to define and register the different WARP environments.",[501,5891,5892,5903],{},[504,5893,5894,5902],{},[441,5895,5898,5899,5901],{"href":5896,"rel":5897},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fstatic\u002Fmdm\u002Fmultiple-orgs\u002FCloudflareWARP.mobileconfig",[445],"Download a sample ",[573,5900,5888],{}," file"," directly from Cloudflare.",[504,5904,5905],{},"Below is an example of what this configuration looks like:",[567,5907,5911],{"className":5908,"code":5909,"language":5910,"meta":423,"style":423},"language-xml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\u003C!DOCTYPE plist PUBLIC \"-\u002F\u002FApple\u002F\u002FDTD PLIST 1.0\u002F\u002FEN\" \"http:\u002F\u002Fwww.apple.com\u002FDTDs\u002FPropertyList-1.0.dtd\">\n\u003Cplist version=\"1.0\">\n\u003Cdict>\n  \u003Ckey>PayloadContent\u003C\u002Fkey>\n  \u003Carray>\n    \u003Cdict>\n      \u003Ckey>PayloadDisplayName\u003C\u002Fkey>\n      \u003Cstring>Warp Configuration\u003C\u002Fstring>\n      \u003Ckey>PayloadIdentifier\u003C\u002Fkey>\n      \u003Cstring>com.cloudflare.warp.CB8B22D4-50E1-48E8-8874-A7594627013A\u003C\u002Fstring>\n      \u003Ckey>PayloadOrganization\u003C\u002Fkey>\n      \u003Cstring>Cloudflare Ltd.\u003C\u002Fstring>\n      \u003Ckey>PayloadType\u003C\u002Fkey>\n      \u003Cstring>com.cloudflare.warp\u003C\u002Fstring>\n      \u003Ckey>PayloadUUID\u003C\u002Fkey>\n      \u003Cstring>CB8B22D4-50E1-48E8-8874-A7594627013A\u003C\u002Fstring>\n      \u003Ckey>PayloadVersion\u003C\u002Fkey>\n      \u003Cinteger>1\u003C\u002Finteger>\n      \u003Ckey>configs\u003C\u002Fkey>\n      \u003Carray>\n        \u003Cdict>\n          \u003Ckey>organization\u003C\u002Fkey>\n          \u003Cstring>your-team-name-1\u003C\u002Fstring>\n          \u003Ckey>display_name\u003C\u002Fkey>\n          \u003Cstring>Team 1\u003C\u002Fstring>\n        \u003C\u002Fdict>\n        \u003Cdict>\n          \u003Ckey>organization\u003C\u002Fkey>\n          \u003Cstring>your-team-name-2\u003C\u002Fstring>\n          \u003Ckey>display_name\u003C\u002Fkey>\n          \u003Cstring>Team 2\u003C\u002Fstring>\n        \u003C\u002Fdict>\n      \u003C\u002Farray>\n    \u003C\u002Fdict>\n  \u003C\u002Farray>\n  \u003Ckey>PayloadDisplayName\u003C\u002Fkey>\n  \u003Cstring>Cloudflare WARP\u003C\u002Fstring>\n  \u003Ckey>PayloadIdentifier\u003C\u002Fkey>\n  \u003Cstring>cloudflare_warp\u003C\u002Fstring>\n  \u003Ckey>PayloadOrganization\u003C\u002Fkey>\n  \u003Cstring>Cloudflare, Ltd.\u003C\u002Fstring>\n  \u003Ckey>PayloadRemovalDisallowed\u003C\u002Fkey>\n  \u003Cfalse\u002F>\n  \u003Ckey>PayloadScope\u003C\u002Fkey>\n  \u003Cstring>System\u003C\u002Fstring>\n  \u003Ckey>PayloadType\u003C\u002Fkey>\n  \u003Cstring>Configuration\u003C\u002Fstring>\n  \u003Ckey>PayloadUUID\u003C\u002Fkey>\n  \u003Cstring>2B7763B8-64F6-41EB-AA5E-7761651B8131\u003C\u002Fstring>\n  \u003Ckey>PayloadVersion\u003C\u002Fkey>\n  \u003Cinteger>1\u003C\u002Finteger>\n\u003C\u002Fdict>\n\u003C\u002Fplist>\n","xml",[573,5912,5913,5918,5923,5928,5933,5938,5943,5948,5953,5958,5963,5968,5973,5978,5983,5988,5993,5998,6003,6008,6013,6018,6023,6028,6033,6038,6043,6048,6052,6056,6061,6065,6070,6074,6080,6086,6092,6098,6104,6110,6116,6122,6128,6134,6140,6146,6152,6158,6164,6170,6176,6182,6188,6194],{"__ignoreMap":423},[576,5914,5915],{"class":578,"line":579},[576,5916,5917],{},"\u003C?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",[576,5919,5920],{"class":578,"line":597},[576,5921,5922],{},"\u003C!DOCTYPE plist PUBLIC \"-\u002F\u002FApple\u002F\u002FDTD PLIST 1.0\u002F\u002FEN\" \"http:\u002F\u002Fwww.apple.com\u002FDTDs\u002FPropertyList-1.0.dtd\">\n",[576,5924,5925],{"class":578,"line":603},[576,5926,5927],{},"\u003Cplist version=\"1.0\">\n",[576,5929,5930],{"class":578,"line":610},[576,5931,5932],{},"\u003Cdict>\n",[576,5934,5935],{"class":578,"line":620},[576,5936,5937],{},"  \u003Ckey>PayloadContent\u003C\u002Fkey>\n",[576,5939,5940],{"class":578,"line":625},[576,5941,5942],{},"  \u003Carray>\n",[576,5944,5945],{"class":578,"line":631},[576,5946,5947],{},"    \u003Cdict>\n",[576,5949,5950],{"class":578,"line":772},[576,5951,5952],{},"      \u003Ckey>PayloadDisplayName\u003C\u002Fkey>\n",[576,5954,5955],{"class":578,"line":1124},[576,5956,5957],{},"      \u003Cstring>Warp Configuration\u003C\u002Fstring>\n",[576,5959,5960],{"class":578,"line":1132},[576,5961,5962],{},"      \u003Ckey>PayloadIdentifier\u003C\u002Fkey>\n",[576,5964,5965],{"class":578,"line":1140},[576,5966,5967],{},"      \u003Cstring>com.cloudflare.warp.CB8B22D4-50E1-48E8-8874-A7594627013A\u003C\u002Fstring>\n",[576,5969,5970],{"class":578,"line":1148},[576,5971,5972],{},"      \u003Ckey>PayloadOrganization\u003C\u002Fkey>\n",[576,5974,5975],{"class":578,"line":1156},[576,5976,5977],{},"      \u003Cstring>Cloudflare Ltd.\u003C\u002Fstring>\n",[576,5979,5980],{"class":578,"line":1164},[576,5981,5982],{},"      \u003Ckey>PayloadType\u003C\u002Fkey>\n",[576,5984,5985],{"class":578,"line":1172},[576,5986,5987],{},"      \u003Cstring>com.cloudflare.warp\u003C\u002Fstring>\n",[576,5989,5990],{"class":578,"line":1183},[576,5991,5992],{},"      \u003Ckey>PayloadUUID\u003C\u002Fkey>\n",[576,5994,5995],{"class":578,"line":1188},[576,5996,5997],{},"      \u003Cstring>CB8B22D4-50E1-48E8-8874-A7594627013A\u003C\u002Fstring>\n",[576,5999,6000],{"class":578,"line":1196},[576,6001,6002],{},"      \u003Ckey>PayloadVersion\u003C\u002Fkey>\n",[576,6004,6005],{"class":578,"line":1737},[576,6006,6007],{},"      \u003Cinteger>1\u003C\u002Finteger>\n",[576,6009,6010],{"class":578,"line":1743},[576,6011,6012],{},"      \u003Ckey>configs\u003C\u002Fkey>\n",[576,6014,6015],{"class":578,"line":1754},[576,6016,6017],{},"      \u003Carray>\n",[576,6019,6020],{"class":578,"line":2417},[576,6021,6022],{},"        \u003Cdict>\n",[576,6024,6025],{"class":578,"line":2872},[576,6026,6027],{},"          \u003Ckey>organization\u003C\u002Fkey>\n",[576,6029,6030],{"class":578,"line":2881},[576,6031,6032],{},"          \u003Cstring>your-team-name-1\u003C\u002Fstring>\n",[576,6034,6035],{"class":578,"line":2889},[576,6036,6037],{},"          \u003Ckey>display_name\u003C\u002Fkey>\n",[576,6039,6040],{"class":578,"line":2897},[576,6041,6042],{},"          \u003Cstring>Team 1\u003C\u002Fstring>\n",[576,6044,6045],{"class":578,"line":2902},[576,6046,6047],{},"        \u003C\u002Fdict>\n",[576,6049,6050],{"class":578,"line":2909},[576,6051,6022],{},[576,6053,6054],{"class":578,"line":2917},[576,6055,6027],{},[576,6057,6058],{"class":578,"line":2925},[576,6059,6060],{},"          \u003Cstring>your-team-name-2\u003C\u002Fstring>\n",[576,6062,6063],{"class":578,"line":2936},[576,6064,6037],{},[576,6066,6067],{"class":578,"line":2944},[576,6068,6069],{},"          \u003Cstring>Team 2\u003C\u002Fstring>\n",[576,6071,6072],{"class":578,"line":2951},[576,6073,6047],{},[576,6075,6077],{"class":578,"line":6076},34,[576,6078,6079],{},"      \u003C\u002Farray>\n",[576,6081,6083],{"class":578,"line":6082},35,[576,6084,6085],{},"    \u003C\u002Fdict>\n",[576,6087,6089],{"class":578,"line":6088},36,[576,6090,6091],{},"  \u003C\u002Farray>\n",[576,6093,6095],{"class":578,"line":6094},37,[576,6096,6097],{},"  \u003Ckey>PayloadDisplayName\u003C\u002Fkey>\n",[576,6099,6101],{"class":578,"line":6100},38,[576,6102,6103],{},"  \u003Cstring>Cloudflare WARP\u003C\u002Fstring>\n",[576,6105,6107],{"class":578,"line":6106},39,[576,6108,6109],{},"  \u003Ckey>PayloadIdentifier\u003C\u002Fkey>\n",[576,6111,6113],{"class":578,"line":6112},40,[576,6114,6115],{},"  \u003Cstring>cloudflare_warp\u003C\u002Fstring>\n",[576,6117,6119],{"class":578,"line":6118},41,[576,6120,6121],{},"  \u003Ckey>PayloadOrganization\u003C\u002Fkey>\n",[576,6123,6125],{"class":578,"line":6124},42,[576,6126,6127],{},"  \u003Cstring>Cloudflare, Ltd.\u003C\u002Fstring>\n",[576,6129,6131],{"class":578,"line":6130},43,[576,6132,6133],{},"  \u003Ckey>PayloadRemovalDisallowed\u003C\u002Fkey>\n",[576,6135,6137],{"class":578,"line":6136},44,[576,6138,6139],{},"  \u003Cfalse\u002F>\n",[576,6141,6143],{"class":578,"line":6142},45,[576,6144,6145],{},"  \u003Ckey>PayloadScope\u003C\u002Fkey>\n",[576,6147,6149],{"class":578,"line":6148},46,[576,6150,6151],{},"  \u003Cstring>System\u003C\u002Fstring>\n",[576,6153,6155],{"class":578,"line":6154},47,[576,6156,6157],{},"  \u003Ckey>PayloadType\u003C\u002Fkey>\n",[576,6159,6161],{"class":578,"line":6160},48,[576,6162,6163],{},"  \u003Cstring>Configuration\u003C\u002Fstring>\n",[576,6165,6167],{"class":578,"line":6166},49,[576,6168,6169],{},"  \u003Ckey>PayloadUUID\u003C\u002Fkey>\n",[576,6171,6173],{"class":578,"line":6172},50,[576,6174,6175],{},"  \u003Cstring>2B7763B8-64F6-41EB-AA5E-7761651B8131\u003C\u002Fstring>\n",[576,6177,6179],{"class":578,"line":6178},51,[576,6180,6181],{},"  \u003Ckey>PayloadVersion\u003C\u002Fkey>\n",[576,6183,6185],{"class":578,"line":6184},52,[576,6186,6187],{},"  \u003Cinteger>1\u003C\u002Finteger>\n",[576,6189,6191],{"class":578,"line":6190},53,[576,6192,6193],{},"\u003C\u002Fdict>\n",[576,6195,6197],{"class":578,"line":6196},54,[576,6198,6199],{},"\u003C\u002Fplist>\n",[501,6201,6202,6212,6225,6235,6240,6256,6268,6286,6302],{},[504,6203,6204,6205,463,6208,6211],{},"Replace ",[573,6206,6207],{},"your-team-name-1",[573,6209,6210],{},"your-team-name-2"," with your respective Cloudflare Zero Trust team names.",[504,6213,5217,6214,6217,6218,6221,6222,6224],{},[573,6215,6216],{},"uuidgen"," in your Terminal to generate unique UUIDs, and use them to replace the placeholder ",[573,6219,6220],{},"PayloadUUID"," values in the ",[573,6223,5888],{}," file.",[504,6226,6227,6228,6231,6232,6234],{},"Make sure that the ",[573,6229,6230],{},"PayloadIdentifier"," string also contains the updated ",[573,6233,6220],{}," to keep the profile distinct.",[504,6236,6237,6238,6224],{},"Save your edited ",[573,6239,5888],{},[504,6241,1770,6242,6245,6246,6249,6250,6252],{},[461,6243,6244],{},"System Settings"," on your Mac, search for ",[461,6247,6248],{},"Profiles",", and select it.",[4303,6251],{},[432,6253],{"alt":6254,"src":6255},"macOS System Settings Profiles pane","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-system-settings-profiles.webp",[504,6257,2105,6258,6261,6262,6264],{},[461,6259,6260],{},"Install, view or remove..."," to begin adding your new configuration profile.",[4303,6263],{},[432,6265],{"alt":6266,"src":6267},"macOS Profiles install view or remove button","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-profiles-view-remove.webp",[504,6269,878,6270,6273,6274,6224,6276,6278,6282],{},[461,6271,6272],{},"+"," (plus) icon in the bottom-left corner and select your saved ",[573,6275,5888],{},[4303,6277],{},[432,6279],{"alt":6280,"src":6281},"macOS Profiles plus button to add a new profile","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-profiles-add-profile.webp",[432,6283],{"alt":6284,"src":6285},"Selecting the mobileconfig file on macOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-select-mobileconfig-file.webp",[504,6287,6288,6289,6291,6292,6295,6296,6298],{},"Select ",[461,6290,4145],{}," and click ",[461,6293,6294],{},"Install"," to apply the configuration.",[4303,6297],{},[432,6299],{"alt":6300,"src":6301},"Confirming Cloudflare WARP profile installation on macOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fmacos-install-cloudflare-warp-profile.webp",[504,6303,6304,6305,6307],{},"Restart your Cloudflare WARP client. You should now see the multi-profile switcher in the user interface:",[4303,6306],{},[432,6308],{"alt":6309,"src":6310},"Cloudflare WARP client with multi-profile switcher on macOS","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002Fcloudflare-warp-multi-profile-switcher.webp",[491,6312,4970],{"id":4969},[428,6314,6315],{},"The Cloudflare WARP client acts as a critical security point on user devices, making Zero Trust Network Access both robust and highly practical. Keeping internal resources isolated from the public internet ensures that every connection attempt is securely authenticated, evaluated, and audited.",[491,6317,1866],{"id":1865},[501,6319,6320,6327,6334,6341],{},[504,6321,6322],{},[441,6323,6326],{"href":6324,"rel":6325},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fteam-and-resources\u002Fdevices\u002Fcloudflare-one-client\u002Fdeployment\u002Fmdm-deployment\u002F#prepare-file-for-mdm-deployment",[445],"Managed Deployment Preparation",[504,6328,6329],{},[441,6330,6333],{"href":6331,"rel":6332},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fteam-and-resources\u002Fdevices\u002Fcloudflare-one-client\u002Fdeployment\u002Fmdm-deployment\u002Fswitch-organizations\u002F",[445],"Switch Between Zero Trust Organizations",[504,6335,6336],{},[441,6337,6340],{"href":6338,"rel":6339},"https:\u002F\u002Fblog.cloudflare.com\u002Fintroducing-warp-connector-paving-the-path-to-any-to-any-connectivity-2\u002F",[445],"Introducing WARP Connector: Paving the Path to Any-to-Any Connectivity",[504,6342,6343],{},[441,6344,6347],{"href":6345,"rel":6346},"https:\u002F\u002Fdevelopers.cloudflare.com\u002Fcloudflare-one\u002Fteam-and-resources\u002Fdevices\u002Fcloudflare-one-client\u002F",[445],"Cloudflare One Client Documentation",[1891,6349,6350],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":423,"searchDepth":597,"depth":603,"links":6352},[6353,6354,6355,6356,6357],{"id":5848,"depth":597,"text":5849},{"id":5862,"depth":597,"text":5863},{"id":5878,"depth":597,"text":5879},{"id":4969,"depth":597,"text":4970},{"id":1865,"depth":597,"text":1866},[5003,5827],"2026-07-04","Configure and switch multiple Cloudflare WARP organisations on macOS using a .mobileconfig file. A complete MDM guide for IT admins.","https:\u002F\u002Finimages.techvoyage.dev\u002Farticles\u002FSwitch%20Between%20Multiple%20Cloudflare%20WARP%20Orgs%20on%20Mac\u002FEN-Switch-Between-Multiple-Cloudflare-WARP-Orgs-on-Mac.webp","Configure Multiple Cloudflare WARP Profiles on macOS",{"schemaOrg":6364,"robots":1929,"sitemap":6366},[6365],{"@type":1928,"headline":398,"description":6360},{"lastmod":6359},{"title":6362,"description":6360,"ogTitle":398,"ogDescription":6360,"twitterTitle":398,"twitterDescription":6360},[6369,4145,6370,1938],"macOS","MDM","1b-JmgD0tsBcQooHgG1MNPYYvTAdh8f83JMRp2OWhJ8",1792489981891]