<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Q的小站</title><description>外在的喧嚣，易乱心性；内在的宁静，方得始终</description><link>https://blog.colix.cn/</link><language>zh</language><item><title>AI Search接入博客</title><link>https://blog.colix.cn/posts/%E5%8D%9A%E5%AE%A2/cloudflare-ai-search/</link><guid isPermaLink="true">https://blog.colix.cn/posts/%E5%8D%9A%E5%AE%A2/cloudflare-ai-search/</guid><description>使用Cloudflare RAG服务构建AI知识库和AI增强搜索</description><pubDate>Wed, 18 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;前言&lt;/h2&gt;
&lt;p&gt;偶然间看到Cloudflare的ai search，不需要自己配置向量化模型和问答模型就可以完成ai知识库配置，只需导入内容即可，遂尝试构建自己的ai知识库，并接入博客作为ai增强搜索以及ai知识库问答助手&lt;/p&gt;
&lt;h2&gt;知识库AI助手接入&lt;/h2&gt;
&lt;h3&gt;搭建&lt;/h3&gt;
&lt;p&gt;在cloudflare中&lt;code&gt;AI --&amp;gt;AI搜索&lt;/code&gt;中创建项目，数据来源可选&lt;code&gt;R2存储桶&lt;/code&gt;和&lt;code&gt;网站&lt;/code&gt;，先搭建知识库，所以这里选&lt;code&gt;R2存储桶&lt;/code&gt;作为数据来源&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.colix.cn/_astro/knowledge-base-build-1.Biwl7w9t_1Sdntm.webp&quot; alt=&quot;知识库构建-1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我习惯使用&lt;code&gt;Obsidian&lt;/code&gt;作为笔记工具，所以使用&lt;code&gt;Obsidian&lt;/code&gt;和&lt;code&gt;Remotely-Save&lt;/code&gt;插件将本地笔记同步到R2存储桶，然后下一步给&lt;code&gt;AI网关&lt;/code&gt;和API等授权，cloudflare会自动处理创建网关等操作，并在ai搜索项目首次创建时进行一次索引构建，后续会定期同步数据源更新索引，也可以手动同步。&lt;/p&gt;
&lt;h3&gt;接入&lt;/h3&gt;
&lt;p&gt;在项目设置中启用&lt;code&gt;Public URL&lt;/code&gt;，完成自定义样式设置，在&lt;code&gt;src/layouts/Layout.astro&lt;/code&gt;文件约&lt;code&gt;159&lt;/code&gt;行位置插入如下代码，替换&lt;code&gt;&amp;lt;hash&amp;gt;&lt;/code&gt;和自定义的样式设置&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- src/layouts/Layout.astro --&amp;gt;
&amp;lt;!-- 在布局文件末尾，&amp;lt;/body&amp;gt; 之前添加 --&amp;gt;
&amp;lt;script type=&quot;module&quot; src=&quot;https://&amp;lt;hash&amp;gt;.search.ai.cloudflare.com/assets/v0.0.25/search-snippet.es.js&quot;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;chat-bubble-snippet
api-url=&quot;https://&amp;lt;hash&amp;gt;.search.ai.cloudflare.com/&quot;
placeholder=&quot;Search...&quot;
theme=&quot;light&quot;
hide-branding=&quot;true&quot;&amp;gt;
&amp;lt;/chat-bubble-snippet&amp;gt;

&amp;lt;style is:global&amp;gt;
/* 可选：自定义样式，作用全局 */
chat-bubble-snippet {
--search-snippet-primary-color: #74a7d8;
--search-snippet-primary-hover: #92c6f7;
--search-snippet-focus-ring: #74a7d8;
--search-snippet-surface: #ffffff;
--search-snippet-hover-background: #ffffff;
--search-snippet-border-color: #f0f9ff;
}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;效果如下：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.colix.cn/_astro/knowledge-base-build-2.D4d-1K4G_14by82.webp&quot; alt=&quot;知识库构建-2&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;AI搜索接入&lt;/h2&gt;
&lt;h3&gt;搭建&lt;/h3&gt;
&lt;p&gt;流程同上，这里作为网页内容搜索，所以数据来源选择&lt;code&gt;网站&lt;/code&gt;，设置完&lt;code&gt;sitemap&lt;/code&gt;后启用&lt;code&gt;Public URL&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;接入&lt;/h3&gt;
&lt;p&gt;编辑&lt;code&gt;src/components/Search.svelte&lt;/code&gt;，这里给出我用ai生成的代码，仅供参考，替换&lt;code&gt;&amp;lt;hash&amp;gt;&lt;/code&gt;和外观配置，可能存在一些小bug，请自行修改优化：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- src/components/Search.svelte --&amp;gt;
&amp;lt;script lang=&quot;ts&quot;&amp;gt;
import I18nKey from &quot;@i18n/i18nKey&quot;;
import { i18n } from &quot;@i18n/translation&quot;;
import Icon from &quot;@iconify/svelte&quot;;
import { url } from &quot;@utils/url-utils.ts&quot;;
import { onMount, tick } from &quot;svelte&quot;;
import type { SearchResult } from &quot;@/global&quot;;

let keywordDesktop = &quot;&quot;;
let keywordMobile = &quot;&quot;;
let result: SearchResult[] = [];
let isSearching = false;
let pagefindLoaded = false;
let initialized = false;
let showAISearch = false; // 新增：控制AI搜索显示状态
let aiSearchContainer: HTMLElement; // 新增：AI搜索容器引用

const fakeResult: SearchResult[] = [
  {
    url: url(&quot;/&quot;),
    meta: {
      title: &quot;This Is a Fake Search Result&quot;,
    },
    excerpt:
      &quot;Because the search cannot work in the &amp;lt;mark&amp;gt;dev&amp;lt;/mark&amp;gt; environment.&quot;,
  },
  {
    url: url(&quot;/&quot;),
    meta: {
      title: &quot;If You Want to Test the Search&quot;,
    },
    excerpt: &quot;Try running &amp;lt;mark&amp;gt;npm build &amp;amp;&amp;amp; npm preview&amp;lt;/mark&amp;gt; instead.&quot;,
  },
];

// 新增：点击外部关闭AI搜索框
const handleClickOutside = (event: MouseEvent) =&amp;gt; {
  if (!showAISearch || !aiSearchContainer) return;
  
  const target = event.target as HTMLElement;
  const searchBar = document.getElementById(&quot;search-bar&quot;);
  const aiButton = searchBar?.querySelector(&apos;button[aria-label=&quot;AI Search&quot;]&apos;);
  
  // 检查点击是否在AI搜索容器、搜索框或AI按钮内部
  const isClickInside = 
    aiSearchContainer.contains(target) ||
    searchBar?.contains(target) ||
    aiButton?.contains(target);
  
  if (!isClickInside) {
    showAISearch = false;
  }
};

// 新增：切换AI搜索显示
const toggleAISearch = async (event?: MouseEvent) =&amp;gt; {
  // 阻止事件冒泡，避免立即触发外部点击检测
  event?.stopPropagation();
  
  showAISearch = !showAISearch;
  
  if (showAISearch) {
    // 等待DOM更新，确保容器已渲染
    await tick();
    
    // 添加全局点击监听器
    setTimeout(() =&amp;gt; {
      document.addEventListener(&apos;click&apos;, handleClickOutside);
    }, 0);
    
    // 如果开启了AI搜索，加载Cloudflare AI搜索库
    if (!document.querySelector(&apos;script[src*=&quot;search.ai.cloudflare.com&quot;]&apos;)) {
      const script = document.createElement(&apos;script&apos;);
      script.type = &apos;module&apos;;
      script.src = &apos;https://&amp;lt;hash&amp;gt;.search.ai.cloudflare.com/assets/v0.0.25/search-snippet.es.js&apos;;
      document.head.appendChild(script);
      
      // 添加样式
      const style = document.createElement(&apos;style&apos;);
      style.textContent = `
        search-bar-snippet {
          --search-snippet-primary-color: #74a7d8;
          --search-snippet-primary-hover: #92c6f7;
          --search-snippet-focus-ring: #74a8d8;
        }
      `;
      document.head.appendChild(style);
    }
  } else {
    // 移除全局点击监听器
    document.removeEventListener(&apos;click&apos;, handleClickOutside);
  }
};

// 新增：组件卸载时清理事件监听器
const cleanup = () =&amp;gt; {
  document.removeEventListener(&apos;click&apos;, handleClickOutside);
};

const togglePanel = () =&amp;gt; {
  const panel = document.getElementById(&quot;search-panel&quot;);
  panel?.classList.toggle(&quot;float-panel-closed&quot;);
};

const setPanelVisibility = (show: boolean, isDesktop: boolean): void =&amp;gt; {
  const panel = document.getElementById(&quot;search-panel&quot;);
  if (!panel || !isDesktop) return;
  if (show) {
    panel.classList.remove(&quot;float-panel-closed&quot;);
  } else {
    panel.classList.add(&quot;float-panel-closed&quot;);
  }
};

const search = async (keyword: string, isDesktop: boolean): Promise&amp;lt;void&amp;gt; =&amp;gt; {
  if (!keyword) {
    setPanelVisibility(false, isDesktop);
    result = [];
    return;
  }
  
  if (!initialized) {
    return;
  }
  
  isSearching = true;
  try {
    let searchResults: SearchResult[] = [];
    if (import.meta.env.PROD &amp;amp;&amp;amp; pagefindLoaded &amp;amp;&amp;amp; window.pagefind) {
      const response = await window.pagefind.search(keyword);
      searchResults = await Promise.all(
        response.results.map((item) =&amp;gt; item.data()),
      );
    } else if (import.meta.env.DEV) {
      searchResults = fakeResult;
    } else {
      searchResults = [];
      console.error(&quot;Pagefind is not available in production environment.&quot;);
    }
    
    result = searchResults;
    setPanelVisibility(result.length &amp;gt; 0, isDesktop);
  } catch (error) {
    console.error(&quot;Search error:&quot;, error);
    result = [];
    setPanelVisibility(false, isDesktop);
  } finally {
    isSearching = false;
  }
};

onMount(() =&amp;gt; {
  const initializeSearch = () =&amp;gt; {
    initialized = true;
    pagefindLoaded =
      typeof window !== &quot;undefined&quot; &amp;amp;&amp;amp;
      !!window.pagefind &amp;amp;&amp;amp;
      typeof window.pagefind.search === &quot;function&quot;;
    console.log(&quot;Pagefind status on init:&quot;, pagefindLoaded);
    
    if (keywordDesktop) search(keywordDesktop, true);
    if (keywordMobile) search(keywordMobile, false);
  };
  
  if (import.meta.env.DEV) {
    console.log(
      &quot;Pagefind is not available in development mode. Using mock data.&quot;,
    );
    initializeSearch();
  } else {
    document.addEventListener(&quot;pagefindready&quot;, () =&amp;gt; {
      console.log(&quot;Pagefind ready event received.&quot;);
      initializeSearch();
    });
    document.addEventListener(&quot;pagefindloaderror&quot;, () =&amp;gt; {
      console.warn(
        &quot;Pagefind load error event received. Search functionality will be limited.&quot;,
      );
      initializeSearch(); // Initialize with pagefindLoaded as false
    });
    
    // Fallback in case events are not caught or pagefind is already loaded by the time this script runs
    setTimeout(() =&amp;gt; {
      if (!initialized) {
        console.log(&quot;Fallback: Initializing search after timeout.&quot;);
        initializeSearch();
      }
    }, 2000); // Adjust timeout as needed
  }
  
  // 返回清理函数
  return cleanup;
});

$: if (initialized &amp;amp;&amp;amp; keywordDesktop) {
  (async () =&amp;gt; {
    await search(keywordDesktop, true);
  })();
}

$: if (initialized &amp;amp;&amp;amp; keywordMobile) {
  (async () =&amp;gt; {
    await search(keywordMobile, false);
  })();
}

// 新增：当AI搜索关闭时，移除事件监听器
$: if (!showAISearch) {
  document.removeEventListener(&apos;click&apos;, handleClickOutside);
}
&amp;lt;/script&amp;gt;

&amp;lt;!-- 桌面版搜索容器 --&amp;gt;
&amp;lt;div class=&quot;hidden lg:flex flex-col relative&quot;&amp;gt;
  &amp;lt;!-- search bar for desktop view --&amp;gt;
  &amp;lt;div id=&quot;search-bar&quot; class=&quot;flex transition-all items-center h-11 mr-2 rounded-lg
        bg-black/[0.04] hover:bg-black/[0.06] focus-within:bg-black/[0.06]
        dark:bg-white/5 dark:hover:bg-white/10 dark:focus-within:bg-white/10
  &quot;&amp;gt;
      &amp;lt;Icon icon=&quot;material-symbols:search&quot; class=&quot;absolute text-[1.25rem] pointer-events-none ml-3 transition my-auto text-black/30 dark:text-white/30&quot;&amp;gt;&amp;lt;/Icon&amp;gt;
      &amp;lt;input placeholder=&quot;{i18n(I18nKey.search)}&quot; bind:value={keywordDesktop} on:focus={() =&amp;gt; search(keywordDesktop, true)}
            class=&quot;transition-all pl-10 text-sm bg-transparent outline-0
          h-full w-40 active:w-60 focus:w-60 text-black/50 dark:text-white/50&quot;
      &amp;gt;
      
      &amp;lt;!-- 新增：AI搜索按钮 --&amp;gt;
      &amp;lt;button 
        on:click={toggleAISearch}
        aria-label=&quot;AI Search&quot;
        class=&quot;ml-2 p-2 rounded-lg transition-colors duration-200 hover:bg-black/[0.08] dark:hover:bg-white/10&quot;
        style:background-color={showAISearch ? &apos;#92c6f7&apos; : &apos;transparent&apos;}
      &amp;gt;
        &amp;lt;Icon 
          icon=&quot;material-symbols:smart-toy-outline&quot; 
          class=&quot;text-[1.25rem] transition-colors {showAISearch ? &apos;text-white&apos; : &apos;text-black/50 dark:text-white/50&apos;}&quot;
        &amp;gt;&amp;lt;/Icon&amp;gt;
      &amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
  
  &amp;lt;!-- AI搜索栏（桌面版，在搜索框下方弹出） --&amp;gt;
  {#if showAISearch}
    &amp;lt;div 
      bind:this={aiSearchContainer}
      class=&quot;absolute top-full left-0 right-0 mt-2 z-50&quot;
      role=&quot;dialog&quot;
      tabindex=&quot;0&quot;
      aria-modal=&quot;true&quot;
      on:click|stopPropagation
      on:keydown={(e) =&amp;gt; {
        if (e.key === &quot;Escape&quot;) {
          showAISearch = false;
        }
      }}
    &amp;gt;
      &amp;lt;search-bar-snippet placeholder=&quot;使用AI搜索...&quot; api-url=&quot;https://&amp;lt;hash&amp;gt;.search.ai.cloudflare.com/&quot; hide-branding=&quot;true&quot;&amp;gt;&amp;lt;/search-bar-snippet&amp;gt;
    &amp;lt;/div&amp;gt;
  {/if}
&amp;lt;/div&amp;gt;

&amp;lt;!-- toggle btn for phone/tablet view --&amp;gt;
&amp;lt;button on:click={togglePanel} aria-label=&quot;Search Panel&quot; id=&quot;search-switch&quot;
        class=&quot;btn-plain scale-animation lg:!hidden rounded-lg w-11 h-11 active:scale-90&quot;&amp;gt;
    &amp;lt;Icon icon=&quot;material-symbols:search&quot; class=&quot;text-[1.25rem]&quot;&amp;gt;&amp;lt;/Icon&amp;gt;
&amp;lt;/button&amp;gt;

&amp;lt;!-- search panel --&amp;gt;
&amp;lt;div id=&quot;search-panel&quot; class=&quot;float-panel float-panel-closed search-panel absolute md:w-[30rem]
top-20 left-4 md:left-[unset] right-4 shadow-2xl rounded-2xl p-2&quot;&amp;gt;
    &amp;lt;!-- search bar inside panel for phone/tablet --&amp;gt;
    &amp;lt;div id=&quot;search-bar-inside&quot; class=&quot;flex relative lg:hidden transition-all items-center h-11 rounded-xl
      bg-black/[0.04] hover:bg-black/[0.06] focus-within:bg-black/[0.06]
      dark:bg-white/5 dark:hover:bg-white/10 dark:focus-within:bg-white/10
  &quot;&amp;gt;
        &amp;lt;Icon icon=&quot;material-symbols:search&quot; class=&quot;absolute text-[1.25rem] pointer-events-none ml-3 transition my-auto text-black/30 dark:text-white/30&quot;&amp;gt;&amp;lt;/Icon&amp;gt;
        &amp;lt;input placeholder=&quot;Search&quot; bind:value={keywordMobile}
               class=&quot;pl-10 absolute inset-0 text-sm bg-transparent outline-0
               focus:w-60 text-black/50 dark:text-white/50&quot;
        &amp;gt;
        
        &amp;lt;!-- 新增：移动端AI搜索按钮 --&amp;gt;
        &amp;lt;button 
          on:click={toggleAISearch}
          aria-label=&quot;AI Search&quot;
          class=&quot;absolute right-2 p-2 rounded-lg transition-colors duration-200 hover:bg-black/[0.08] dark:hover:bg-white/10&quot;
          style:background-color={showAISearch ? &apos;#92c6f7&apos; : &apos;transparent&apos;}
        &amp;gt;
          &amp;lt;Icon 
            icon=&quot;material-symbols:smart-toy-outline&quot; 
            class=&quot;text-[1.25rem] transition-colors {showAISearch ? &apos;text-white&apos; : &apos;text-black/50 dark:text-white/50&apos;}&quot;
          &amp;gt;&amp;lt;/Icon&amp;gt;
        &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
    
    &amp;lt;!-- AI搜索栏（移动端，在搜索框下方） --&amp;gt;
    {#if showAISearch}
      &amp;lt;div 
        class=&quot;lg:hidden mt-2 mb-4 relative z-10&quot; 
        role=&quot;dialog&quot;
        aria-label=&quot;AI Search&quot;
        tabindex=&quot;-1&quot;
        on:click|stopPropagation
        on:keydown={(e) =&amp;gt; {
          if (e.key === &quot;Escape&quot;) {
            showAISearch = false;
          }
        }}
      &amp;gt;
        &amp;lt;!-- 包裹容器，确保AI搜索组件能够正常展开 --&amp;gt;
        &amp;lt;div class=&quot;ai-search-container-mobile&quot;&amp;gt;
          &amp;lt;search-bar-snippet placeholder=&quot;使用AI搜索...&quot; api-url=&quot;https://&amp;lt;hash&amp;gt;.search.ai.cloudflare.com/&quot; hide-branding=&quot;true&quot;&amp;gt;&amp;lt;/search-bar-snippet&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    {/if}
    
    &amp;lt;!-- search results --&amp;gt;
    {#each result as item}
        &amp;lt;a href={item.url}
           class=&quot;transition first-of-type:mt-2 lg:first-of-type:mt-0 group block
       rounded-xl text-lg px-3 py-2 hover:bg-[var(--btn-plain-bg-hover)] active:bg-[var(--btn-plain-bg-active)]&quot;&amp;gt;
            &amp;lt;div class=&quot;transition text-90 inline-flex font-bold group-hover:text-[var(--primary)]&quot;&amp;gt;
                {item.meta.title}&amp;lt;Icon icon=&quot;fa6-solid:chevron-right&quot; class=&quot;transition text-[0.75rem] translate-x-1 my-auto text-[var(--primary)]&quot;&amp;gt;&amp;lt;/Icon&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div class=&quot;transition text-sm text-50&quot;&amp;gt;
                {@html item.excerpt}
            &amp;lt;/div&amp;gt;
        &amp;lt;/a&amp;gt;
    {/each}
&amp;lt;/div&amp;gt;

&amp;lt;style&amp;gt;
  input:focus {
    outline: 0;
  }
  .search-panel {
    max-height: calc(100vh - 100px);
    overflow-y: auto;
  }
  
  /* Cloudflare AI搜索组件样式 */
  search-bar-snippet {
    --search-snippet-primary-color: #74a7d8;
    --search-snippet-primary-hover: #92c6f7;
    --search-snippet-focus-ring: #74a8d8;
    width: 100%;
    border-radius: 0.5rem;
    box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  }
  
  /* 移动端AI搜索容器样式 */
  .ai-search-container-mobile {
    position: relative;
    width: 100%;
    min-height: 60px; /* 确保有最小高度 */
  }
  
  /* 确保AI搜索组件在移动端能够正常展开 */
  .ai-search-container-mobile search-bar-snippet {
    position: static !important; /* 覆盖可能的绝对定位 */
    max-height: none !important; /* 移除高度限制 */
    overflow: visible !important; /* 确保内容可见 */
  }
  
  /* 针对Cloudflare AI搜索组件的特定样式 */
  .ai-search-container-mobile ::ng-deep search-bar-snippet,
  .ai-search-container-mobile ::slotted(search-bar-snippet) {
    position: static !important;
    max-height: none !important;
    overflow: visible !important;
  }
  
  /* 确保搜索结果列表能够正常显示 */
  .search-panel {
    overflow: visible; /* 允许内容溢出 */
  }
  
  /* 当AI搜索激活时，调整搜索面板样式 */
  .search-panel:has(.ai-search-container-mobile search-bar-snippet[expanded]) {
    overflow-y: auto; /* 恢复滚动 */
    max-height: 80vh; /* 增加最大高度 */
  }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;效果如下：
&lt;img src=&quot;https://blog.colix.cn/_astro/ai-search-build-1.CpaRksq9_2aBgze.webp&quot; alt=&quot;AI搜索构建-1&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;完结撒花&lt;/h2&gt;
&lt;p&gt;cf的AI搜索省去了自己配置嵌入模型和前端查询响应模型的繁琐步骤，并且每天提供10k神经元额度，这个评价必须给到夯。目前模型响应速度和国内访问速度都还不错，写完笔记点点&lt;code&gt;Remotely-Save&lt;/code&gt;就能推送到知识库😋&lt;/p&gt;
&lt;h2&gt;题外话&lt;/h2&gt;
&lt;p&gt;AI发展真的太快了，从最初chatgpt发布，只觉得这玩意儿能聊天还挺好玩，受限于没有境外信用卡和网络环境，对gpt的使用仅限于网页聊天。到deepseek发布，第一次知道ai可以通过api接入到自己的程序里面，那时候deepseek每个月还有10元的免费额度，低廉的调用成本带来了巨量的使用量，可能还有竞争对手的攻击，让其api接口一度瘫痪，甚至连官网的reasoner模型都基本无法响应。后来国内各厂商也是紧追其后，阿里、字节等都发布了自己的模型。&lt;/p&gt;
&lt;p&gt;从高中到大学短短几年，见证了ai从娱乐聊天机器人，变成了实打实的生产力工具，自己对ai的依赖也是越来越重。初学逆向时，我经常把整段的代码贴给ai，可往往一个花指令就能骗过ai，到现在比赛，配好agent，配好ida-mcp和wsl，接个powerful的模型api，ai接管了从代码分析到动态调试、接收报错继续修正的所有流程，除了烧token外几乎不需要额外介入。很难想象，赛场上隐藏在屏幕之下和你对线的，可能不是碳基生物。&lt;/p&gt;
&lt;p&gt;openclaw发布后，总能刷到“付费上门安装龙虾”或是“付费卸载龙虾”一类的推文，且不论是博人眼球亦或是确有此事，ai对日常生活渗透之快是不可置否的，使用技术的门槛降低也许是好事，但对于我而言，对ai的依赖总是无声无息的消磨着我学习的欲望，盯着电脑花几个小时调试程序，不如问ai来的快，甚至容易产生&quot;这就是我的水平&quot;的错觉，希望自己能时刻保持清醒，继续学习🫡&lt;/p&gt;
</content:encoded><category>博客</category><category>AI</category><category>建站</category></item><item><title>闲谈</title><link>https://blog.colix.cn/posts/%E5%8D%9A%E5%AE%A2/20260302/</link><guid isPermaLink="true">https://blog.colix.cn/posts/%E5%8D%9A%E5%AE%A2/20260302/</guid><description>博客迁移计划</description><pubDate>Mon, 02 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;寒假&lt;/h1&gt;
&lt;p&gt;原来的博客平台从云服务器上迁移到本地已经有半年了，但是运行博客的主机在寒假期间宕机了，而服务器被我留在了学校里，并且没有配置WOL唤醒一类的重启方式，只能让博客被迫关停了一个月，同样部署在这台主机上的umami也用不了了。为了增加安全性和减少不必要的服务器支出，我计划只保留一到两台大带宽的公网服务器作为穿透主机，将所有服务都迁移到本地的NAS和服务器上。博客主站使用的&lt;code&gt;typecho&lt;/code&gt;框架发布了&lt;code&gt;1.3.0&lt;/code&gt;版本，出于和主题兼容性问题的考虑我也不打算很快升级，但又看到&lt;code&gt;1.2.1&lt;/code&gt;版本有xss漏洞。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;所以想要把博客迁移到这个站点，大概就是这几点原因：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;本地服务器运行的可靠性以及维护的便利性不如云服务器&lt;/li&gt;
&lt;li&gt;动态博客网站存在一定安全隐患&lt;/li&gt;
&lt;li&gt;astro可以直接用腾讯云的eo来部署，可以享受到cdn的加速的同时还无需关心证书续期等问题&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;而&lt;code&gt;fuwari&lt;/code&gt;主题最大的遗憾就是不能支持评论，但是通过参考学习网上的教程，我也试着把&lt;code&gt;twikoo&lt;/code&gt;评论系统加到了这个站点，将&lt;code&gt;twikoo&lt;/code&gt;通过docker部署在了本地的飞牛上。&lt;/p&gt;
&lt;p&gt;说到飞牛，不得不提飞牛NAS在前段时间爆出的重大安全漏洞，只需要在NAS的URL后面加上&lt;code&gt;/app-center-static/serviceicon/myapp/%7B0%7D/?size=../../../../&lt;/code&gt;，无需认证就可以目录穿越访问整个NAS根目录下的文件，也听说有被植入木马的，具体攻击手法不太了解。官方最初似乎是想将补丁插在版本更新里面，对用户只是说公网http明文不安全，没有做出明确的说明，但社区早就传遍了🤦‍♂️。后续官方也是发布了木马查杀脚本和重大安全更新，并停用了所有&lt;code&gt;fn connect&lt;/code&gt;，强制用户更改强密码。万幸的是我当时使用&lt;code&gt;frp穿透&lt;/code&gt;+&lt;code&gt;nginx-proxy-manager反代&lt;/code&gt;，而&lt;code&gt;npm&lt;/code&gt;的&lt;code&gt;Block Common Exploits&lt;/code&gt;选项过滤了目录穿越，随手点的安全配置算是保住了我的NAS😋&lt;/p&gt;
&lt;h1&gt;迁移&lt;/h1&gt;
&lt;p&gt;主要问题，还是评论迁过来比较麻烦（其实也不多），需要写个脚本从数据库提出来改成json格式，文章已经陆续完成迁移。比较担心的是fuwari主题很多地方都有经过大大小小的修改，如果将来主题更新，诸如评论之类可能需要全部重新配置一遍😂&lt;/p&gt;
&lt;h2&gt;twikoo的集成&lt;/h2&gt;
&lt;p&gt;感谢&lt;a href=&quot;https://www.rosmontis.xyz/posts/blog-theme-mod/&quot;&gt;Fuwari 主题魔改 - 给你的Fuwari添加Twikoo评论支持&lt;/a&gt;和&lt;a href=&quot;https://blog.tantalum.life/posts/add-comments-to-fuwari-with-twikoo/&quot;&gt;Astro | 为 Fuwari 主题添加 Twikoo 评论&lt;/a&gt;两篇文章的保姆级教学，包括&lt;code&gt;fuwari&lt;/code&gt;主题的修改以及css的样式设计，这两篇文章已经写得很详细了，这里不多赘述。&lt;/p&gt;
&lt;h2&gt;字体&lt;/h2&gt;
&lt;p&gt;参照文章&lt;a href=&quot;https://aulypc1.github.io/posts/website/use_custom_fonts_in_fuwari/&quot;&gt;在Fuwari使用自定义字体&lt;/a&gt;。我这里将&lt;code&gt;@import url(&quot;https://example.com/css/theme.css&quot;);&lt;/code&gt;添加到了&lt;code&gt;main.css&lt;/code&gt;中，直接引入切片过的字体css。&lt;/p&gt;
&lt;h2&gt;友链&lt;/h2&gt;
&lt;p&gt;参照文章&lt;a href=&quot;https://blog.skarie.top/posts/fuwari/fuwari%E6%B7%BB%E5%8A%A0%E5%8F%8B%E9%93%BE%E9%A1%B5%E9%9D%A2/fuwari%E6%B7%BB%E5%8A%A0%E5%8F%8B%E9%93%BE%E9%A1%B5%E9%9D%A2/&quot;&gt;Fuwari 博客添加友链页面详细教程&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>博客</category><category>建站</category></item><item><title>记一次梯控卡复制</title><link>https://blog.colix.cn/posts/sundry/ic_copy_0/</link><guid isPermaLink="true">https://blog.colix.cn/posts/sundry/ic_copy_0/</guid><description>康拓1梯控</description><pubDate>Wed, 06 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;麻麻说上班要刷梯控卡太麻烦，因此让我帮她拷进手环里，一看她的手环没有nfc，不过没关系，买一张nfc手机贴一样能解决&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;前置知识&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;卡片类型（IC卡）&lt;/th&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;M1卡&lt;/td&gt;
&lt;td&gt;标准卡，UID全球唯一，0扇区0区块不可修改，其余扇区可写&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UID卡&lt;/td&gt;
&lt;td&gt;所有扇区均可写，使用后门指令操作，因此可被防火墙识别后门指令拦截&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CUID卡&lt;/td&gt;
&lt;td&gt;所有扇区均可写，没有后门指令，使用协议标准指令写卡&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FUID卡&lt;/td&gt;
&lt;td&gt;0扇区0区块只允许写入一次，写入后即锁定（一次性写入，写入完成后同M1卡）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UFUID卡&lt;/td&gt;
&lt;td&gt;可手动控制卡是否锁定，锁卡即为M1卡，不锁定即为UID卡&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;其他&lt;/th&gt;
&lt;th&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ID卡&lt;/td&gt;
&lt;td&gt;只有卡号，安全性低，并且频率与IC卡不同，手机nfc读不了&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU卡&lt;/td&gt;
&lt;td&gt;内置CPU、内存等，加密等级高，难解&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;卡片容量
&lt;ul&gt;
&lt;li&gt;标准m1卡及复制卡（s50）：1KB，16扇区&lt;/li&gt;
&lt;li&gt;s70复制卡：4KB，32扇区&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;不得不提一嘴，4KB的复制卡真的很难买到😒&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;滚动码：梯控常用，每刷一次卡片滚码和系统同步更新，制作复制卡并刷卡后即会导致原卡滚码位与系统内不一致，导致原卡报废，有些系统刷了滚码不一致的卡片也可能会封卡号，导致旧卡新卡都报废，复制可以使用gdm卡，一卡变多卡需要发新卡&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;工具准备&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;1kb cuid复制卡&lt;/li&gt;
&lt;li&gt;小熊猫gp3&lt;/li&gt;
&lt;li&gt;pcr532软件&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;尝试&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;首先用pcr532软件进行解卡，解出的数据是16个扇区，并且根据分析是康拓1梯控（这时也许可以直接发卡，这里只研究复制）&lt;/li&gt;
&lt;li&gt;我使用了一张1KB的cuid复制卡进行复制写入&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;交给麻麻后让她去试一试，结果说刷卡不通过，只能刷了原来的卡&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;再次解卡，这次同时解密了原卡和被刷过的复制卡，发现了两点问题：
&lt;ol&gt;
&lt;li&gt;原卡的滚码位没有发生变化，说明没有滚码验证机制，我不需要使用专门的gdm卡进行复制&lt;/li&gt;
&lt;li&gt;复制卡的0扇区0块被清空了，显然系统做了防复制卡的机制：尝试写入0扇区0块，因为标准m1卡的0扇区0块出厂写死，是不可更改的，能写入的必然是复制卡&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;这么看，只需要用一张1KB的fuid或者ufuid复制卡就可以解决这个问题&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;结束&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;其实如果仅仅需要复制，其实gp3就有变色龙功能，可以直接模拟m1卡&lt;/li&gt;
&lt;li&gt;pcr532的Windows端有bug，打不开4kb s70的dump文件，可以用手机pcr532&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;更多教程&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&amp;lt;a href=&quot;https://www.bilibili.com/video/BV11h4y1T7Pm&quot;&amp;gt;【教程】手把手教你玩转IC卡&amp;lt;/a&amp;gt;&lt;/p&gt;
</content:encoded><category>杂</category><category>IC卡</category></item><item><title>fnOS体验</title><link>https://blog.colix.cn/posts/sundry/fnnas/</link><guid isPermaLink="true">https://blog.colix.cn/posts/sundry/fnnas/</guid><description>新兴国产nas系统</description><pubDate>Mon, 07 Jul 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;作为第一批体验飞牛nas系统的玩家，这款国产nas系统刚发布时，我的主力还是在用黑群，没有过多关注，现在似乎热度挺高，又拿出来玩玩，顺便写一篇使用体验&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;安装&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;在虚拟机里设置好网卡桥接，路由器会为虚拟机中的飞牛os分配新的ip，注意管理员用户名密码同ssh用户名密码，重置是比较麻烦的，要重置linux密码&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;我这里用的是最初公测的版本
&lt;img src=&quot;https://blog.colix.cn/_astro/4014595433.ivvbIa61_2iN3eU.webp&quot; alt=&quot;早期公测版&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;优点&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;作为首款国产nas系统，初次接触让我很震惊的是居然兼容x86平台，而且免费，这让这款nas系统的可玩性大大提高，随便买一台二三十的工控板就可以跑起来。&lt;/li&gt;
&lt;li&gt;在这之前想要在第三方硬件上玩nas，除了群晖能抄到作业外，铁威马、威联通这些nas自己的系统很少能装在第三方平台上，黑群的兼容性也并不是绝对完美&lt;/li&gt;
&lt;li&gt;飞牛nas还提供免费的公网访问，甚至其FN Connect还提供免费的域名和证书，现在带宽策略进行了优化，可以付费获得更高的带宽，相比之下黑群是用不了qc的，公网访问除非爆金币洗白或者开ipv6~~，现在要运营商给v4地址咱就别做梦了~~
&lt;img src=&quot;https://blog.colix.cn/_astro/2378226301.Cmbb8bS3_102579.webp&quot; alt=&quot;FN Connect&quot; /&gt;&lt;/li&gt;
&lt;li&gt;相册和影视功能也是一大亮点，对标极空间、绿联这些国产nas的相册功能，飞牛的相册功能做的是不错的
&lt;img src=&quot;https://blog.colix.cn/_astro/19558066.r13CNyiq_9BDCb.webp&quot; alt=&quot;相册&quot; /&gt;&lt;/li&gt;
&lt;li&gt;飞牛nas的ui设计也非常符合我的审美，简洁清爽
&lt;img src=&quot;https://blog.colix.cn/_astro/671198544.BS-0E3wI_ZV4YNp.webp&quot; alt=&quot;飞牛&quot; /&gt;
&lt;img src=&quot;https://blog.colix.cn/_astro/3692345863.BzrmkRtB_ZyjiVX.webp&quot; alt=&quot;群晖&quot; /&gt;&lt;/li&gt;
&lt;li&gt;飞牛nas虽然应用商店套件较少，但是支持docker，可玩性很强，虽然群晖同样支持，但是受限于硬件性能，不如飞牛DIY硬件玩的爽
&lt;img src=&quot;https://blog.colix.cn/_astro/3663497305.BxdEQsdV_21FnEE.webp&quot; alt=&quot;应用商店&quot; /&gt;
&lt;img src=&quot;https://blog.colix.cn/_astro/3921050231.Ci52EGJ3_2fHThW.webp&quot; alt=&quot;Docker&quot; /&gt;&lt;/li&gt;
&lt;li&gt;在系统更新方面，对比黑群是更省心的，黑群一更新就废了，当然白群没有这个问题
&lt;img src=&quot;https://blog.colix.cn/_astro/3628702233._HRJrHSk_2bIXJY.webp&quot; alt=&quot;系统更新&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;不足&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;这里使用的是最初的飞牛公测版，后面很多功能应该有所升级完善&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;群晖支持系统盘RAID1，飞牛似乎是不支持的，稳定性略低，个人感觉影响不大&lt;/li&gt;
&lt;li&gt;仅支持传统RAID（0/1/5/6/10），但玩得起RAID10的估计也不会拿这个当主力 &lt;s&gt;，就是说咱垃圾佬也够用了&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;不支持kvm，只能用docker&lt;/li&gt;
&lt;li&gt;GPU直通加速优化没有做的很完善&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;总的来说&lt;/h1&gt;
&lt;p&gt;都说nas的尽头是群晖，群晖给人一种硬核的风格体验，但是飞牛作为一款新兴国产nas系统，兼容x86平台，社区生态逐渐完善，ui做的不错，应该说是低成本、低技术门槛体验nas的最佳选择了。&lt;/p&gt;
&lt;p&gt;如果你是追求极致稳定的商务男和不在乎白群这点小钱的富哥，那也许群晖完善而封闭的生态、强大的虚拟化功能以及稳定的系统更新更适合你；但对于多数入门玩家而言，飞牛的功能完全可以满足所有需求了，而不需要花费大量的时间精力整dsm系统，更多功能请自行探索&lt;/p&gt;
</content:encoded><category>杂</category></item><item><title>第二届“Parloo”应急响应CTF</title><link>https://blog.colix.cn/posts/ctf/parloo_2/</link><guid isPermaLink="true">https://blog.colix.cn/posts/ctf/parloo_2/</guid><description>第二届“Parloo”应急响应赛后反思</description><pubDate>Wed, 28 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;第一次参加应急响应比赛，题目不是很难，比较新奇&lt;s&gt;估计太实战也很少有人做得出来了&lt;/s&gt;&lt;/p&gt;
&lt;h1&gt;应急响应&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;这部分火眼立大功，大部分flag丢进火眼全局搜索就已经出来了，虽然最后有两个base64没搜出来&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;关于后门文件（非木马）md5，其实是将&lt;code&gt;cmd&lt;/code&gt;程序复制改名为&lt;code&gt;sethc.exe&lt;/code&gt;，也就是替换了粘滞键，其实替换&lt;code&gt;Utilman.exe&lt;/code&gt;也可以，在win7就有一个bug用于重置密码：异常断电后进入异常恢复，在打开版权声明的时候用的是记事本😂，在记事本的文件管理窗口就可以将&lt;code&gt;Utilman.exe&lt;/code&gt;替换为&lt;code&gt;cmd.exe&lt;/code&gt;，再正常启动后就可以在锁屏界面就可以按五下shift调出cmd窗口，用&lt;code&gt;net user&lt;/code&gt;重置密码，这题应该也是这个意思&lt;/li&gt;
&lt;li&gt;反制攻击机，拿回收站文件，CVE-2024-23692 HFS2.3远程代码执行漏洞，可以执行任意代码自然就可以爆出来，但也可以更暴力一点：
&lt;ol&gt;
&lt;li&gt;执行&lt;code&gt;reg query &quot;HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp&quot; /v PortNumber&lt;/code&gt;拿远程桌面端口&lt;/li&gt;
&lt;li&gt;执行&lt;code&gt;net user Administrator &quot;password&quot;&lt;/code&gt;改掉管理员密码&lt;/li&gt;
&lt;li&gt;远程登录看回收站flag文件&lt;/li&gt;
&lt;li&gt;&lt;s&gt;顺便把flag改掉&lt;/s&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;木马的分析，主要看各种日志、bash_history、自启动任务，找到丢云沙箱或ida简单看下&lt;/li&gt;
&lt;li&gt;横向扫描工具，看到HFS上有个nmap盲猜对了，在服务器上名字改过，不叫nmap&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Misc&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;两题0解，流量分析，我也不会&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;勒索病毒&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;给的是一个被勒索的Windows计算机远程桌面，文件是都被锁了，大致看一下有XAMPP和wordpress，估计就是从博客打进来的，一般都是博客洞最多&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;加密器放在用户文件夹下，文件名比较明显异常&lt;/li&gt;
&lt;li&gt;数据库文件名称在XAMPP的MySQL日志里找&lt;/li&gt;
&lt;li&gt;漏洞CVE编号这个带点猜的成分，在网上搜wordpress当前版本的公开漏洞，没找到，再看wordpress，有Kubio插件，再去搜插件漏洞，找到&lt;strong&gt;CVE-2025-2294 - Kubio AI Page Builder 本地文件包含漏洞&lt;/strong&gt;，那应该就是这跑不了了&lt;/li&gt;
&lt;li&gt;网站管理员邮箱也是很离谱，居然在浏览器历史页面打开后有缓存，但是一刷新就再也回不来了（靶机是断网环境），也许这是非预期？&lt;/li&gt;
&lt;li&gt;攻击者邮箱更是让人挠头，yopmail那玩意儿是不需要密码的公开邮箱，要拿管理员邮箱登上去才能找到😒（我一度觉得就是勒索信里留下的联系邮箱，但是怎么交都不对）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;作为国内首个应急响应ctf，比赛整体是想要脱离传统ctf的模式，模拟实战环境，挺新颖的，难度控制的比较低，攻击的手法也都是比较简单经典的，比如木马有用metasploit编译的（第一眼die看到是用MASM编译的，后来想到metasploit本身就支持对导出的载荷加壳加密之类的操作），希望下一届能办更好&lt;/p&gt;
</content:encoded><category>CTF</category><category>应急响应</category></item><item><title>ImgHub图床</title><link>https://blog.colix.cn/posts/sundry/imgbed/</link><guid isPermaLink="true">https://blog.colix.cn/posts/sundry/imgbed/</guid><description>配合cf等不可写场景存储图片</description><pubDate>Wed, 02 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;续上文&lt;a href=&quot;https://blog.colix.cn/posts/try/typecho/vercel_typecho/&quot;&gt;在vercel部署博客&lt;/a&gt;，railway的数据库试用额度快用完了，但是想要把小组的网站尽量低成本的运行下去，于是找到了更完善的方案，并部署图床解决图片的存储问题&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;准备：&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;MySQL数据库：&lt;a href=&quot;https://sqlpub.com/&quot;&gt;SQLPub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;图床：&lt;a href=&quot;https://github.com/MarSeventh/CloudFlare-ImgBed&quot;&gt;ImgHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;cloudflare账户&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;SQLPub&lt;/h2&gt;
&lt;p&gt;在网上无意发现SQLHub提供500m的免费空间，升级9.9/年就有1g，存储文本5m都绰绰有余，也是很良心了，希望可以一直运营下去&lt;/p&gt;
&lt;p&gt;数据库连接配置在&lt;code&gt;config.inc.php&lt;/code&gt;中改就行，同样是MySQL数据从railway迁移还是很方便的，方法网上都有&lt;/p&gt;
&lt;h2&gt;ImgHub&lt;/h2&gt;
&lt;p&gt;图床项目就叫&lt;a href=&quot;https://github.com/MarSeventh/CloudFlare-ImgBed&quot;&gt;CloudFlare-ImgBed&lt;/a&gt;，顾名思义是放在cloudflare上，页面放cf的pages，存储就用cf的R2存储桶，有10g空间，100000次请求和1000次删除（好像），小网站也是足够用的&lt;/p&gt;
&lt;p&gt;先创建R2存储桶，设置默认即可
&lt;img src=&quot;https://blog.colix.cn/_astro/1477591062.DUm1ji21_1bV0yW.webp&quot; alt=&quot;2025-04-01T02:22:58.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;创建KV命名空间，名称&lt;code&gt;img_url&lt;/code&gt;
&lt;img src=&quot;https://blog.colix.cn/_astro/2021592789.C5bpxjXp_2fCYfL.webp&quot; alt=&quot;2025-04-01T02:27:27.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;然后创建pages，连接git，fork之后直接deploy就行（注意不是workers）
&lt;img src=&quot;https://blog.colix.cn/_astro/1902433217.mDR2W66f_2wd41a.webp&quot; alt=&quot;2025-04-01T02:24:04.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;部署成功后，来到设置，选择绑定，分别绑定KV命名空间和R2存储桶
&lt;img src=&quot;https://blog.colix.cn/_astro/445901927.C4iJsM-P_Z1uAPTR.webp&quot; alt=&quot;2025-04-01T02:26:18.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最后设置环境变量，这里我只设置了几个需要用到的，分别是访问密码和后台用户密码，更多配置方法的可以看&lt;a href=&quot;https://github.com/MarSeventh/CloudFlare-ImgBed&quot;&gt;CloudFlare-ImgBed&lt;/a&gt;项目GitHub主页
&lt;img src=&quot;https://blog.colix.cn/_astro/443553622.D3CLtxbI_iopvp.webp&quot; alt=&quot;2025-04-01T02:28:55.png&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;至此创建完成，可以在图床上传图片并获取外联，访问&lt;code&gt;https://domain/dashboard&lt;/code&gt;访问后台管理&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;七牛云、腾讯等平台的对象存储都可以存图片，但是图床随传随用更方便&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>杂</category><category>图床</category></item><item><title>vercel部署typecho</title><link>https://blog.colix.cn/posts/sundry/vercel_typecho/</link><guid isPermaLink="true">https://blog.colix.cn/posts/sundry/vercel_typecho/</guid><description>typecho建站</description><pubDate>Tue, 01 Apr 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;前言&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;网上教程都已经不适用最新版本的部署，抄作业都跑不起来，所以写个自己实际部署过程&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;准备&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GitHub账号&lt;/li&gt;
&lt;li&gt;railway账号&lt;/li&gt;
&lt;li&gt;typecho源码&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;创建数据库&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;最初是想使用vercel提供的postgres数据库，省点力，虽然Typecho是支持postgres的，但是初始化过程中却提示无法加载支持，是个谜。有能力可以尝试解决&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://railway.com&quot;&gt;点击这里&lt;/a&gt;前往railway官网
可以直接使用GitHub登录，登陆后创建MySQL数据库
点击create，选择database
&lt;img src=&quot;https://blog.colix.cn/_astro/3801958192.UMxRNpcd_15Wj3d.webp&quot; alt=&quot;选择MySQL&quot; /&gt;
记录以下变量值备用
&lt;img src=&quot;https://blog.colix.cn/_astro/552937808.D34odVLi_2gEv2f.webp&quot; alt=&quot;数据库变量&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;改动代码&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;将typecho源码fork至自己的仓库（设置成private），前往&lt;a href=&quot;https://github.com/typecho/typecho&quot;&gt;Typecho&lt;/a&gt; GitHub页面fork&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在根目录下新建&lt;code&gt;api&lt;/code&gt;目录，在&lt;code&gt;api/&lt;/code&gt;目录下新建&lt;code&gt;index.php&lt;/code&gt;文件，并写入以下内容：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?php
$file= __DIR__ . &apos;/..&apos;.$_SERVER[&quot;PHP_SELF&quot;];

if(file_exists($file))
{
   return false;
}
else
{
    require_once __DIR__ . &apos;/../index.php&apos;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;在根目录创建&lt;code&gt;vercel.json&lt;/code&gt;文件，写入以下内容：&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;functions&quot;: {
    &quot;api/index.php&quot;: {
      &quot;runtime&quot;: &quot;vercel-php@0.7.3&quot;
    }
  },
  &quot;routes&quot;: [
    { &quot;src&quot;: &quot;/(.*)&quot;, &quot;dest&quot;: &quot;/api/index.php&quot; }
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;删除写入检测部分代码&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;vercel部署的应用程序没有写入权限，Typecho检测到目录没有写入权限无法继续安装，需要将这部分代码删除或注释&lt;/p&gt;
&lt;p&gt;在根目录&lt;code&gt;install.php&lt;/code&gt;文件中搜索&lt;code&gt;上传目录无法写入&lt;/code&gt;字段，将判断写入权限的部分全部删除或注释&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    if (!$writeable) {
        $errors[] = _t(&apos;上传目录无法写入, 请手动将安装目录下的 %s 目录的权限设置为可写然后继续升级&apos;, $uploadDir);
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;配置Typecho初始化设置&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在项目根目录下创建&lt;code&gt;config.inc.php&lt;/code&gt;文件，写入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?php
/**
 * Typecho Blog Platform
 *
 * @copyright  Copyright (c) 2008 Typecho team (http://www.typecho.org)
 * @license    GNU General Public License 2.0
 * @version    $Id$
 */
/** 开启https */ 
define(&apos;__TYPECHO_SECURE__&apos;,true);

/** 定义根目录 */
define(&apos;__TYPECHO_ROOT_DIR__&apos;, dirname(__FILE__));

/** 定义插件目录(相对路径) */
define(&apos;__TYPECHO_PLUGIN_DIR__&apos;, &apos;/usr/plugins&apos;);

/** 定义模板目录(相对路径) */
define(&apos;__TYPECHO_THEME_DIR__&apos;, &apos;/usr/themes&apos;);

/** 后台路径(相对路径) */
define(&apos;__TYPECHO_ADMIN_DIR__&apos;, &apos;/admin/&apos;);

/** 设置包含路径 */
@set_include_path(get_include_path() . PATH_SEPARATOR .
__TYPECHO_ROOT_DIR__ . &apos;/var&apos; . PATH_SEPARATOR .
__TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__);

/** 载入API支持 */
require_once &apos;Typecho/Common.php&apos;;

/** 程序初始化 */
Typecho_Common::init();

/** 定义数据库参数 */
$db = new Typecho_Db(&apos;Pdo_Mysql&apos;, &apos;typecho_&apos;);
$db-&amp;gt;addServer(array (
  &apos;host&apos; =&amp;gt; &apos;数据库地址&apos;,
  &apos;user&apos; =&amp;gt; &apos;数据库用户名&apos;,
  &apos;password&apos; =&amp;gt; &apos;数据库密码&apos;,
  &apos;charset&apos; =&amp;gt; &apos;utf8mb4&apos;,
  &apos;port&apos; =&amp;gt; 数据库端口,
  &apos;database&apos; =&amp;gt; &apos;数据库名&apos;,
  &apos;engine&apos; =&amp;gt; &apos;MyISAM&apos;,
), Typecho_Db::READ | Typecho_Db::WRITE);
Typecho_Db::set($db);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里的数据库密码等从railway中MySQL数据库Variables中获取，需要注意的是这里的&lt;code&gt;MYSQLHOST&lt;/code&gt;和&lt;code&gt;MYSQLPORT&lt;/code&gt;是内部地址，需要在&lt;code&gt;Settings&lt;/code&gt;页中&lt;code&gt;Networking&lt;/code&gt;获取外网的映射地址
&lt;img src=&quot;https://blog.colix.cn/_astro/1800204246.DuPu0c1A_2ddtw3.webp&quot; alt=&quot;正确的host和port&quot; /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;请将仓库设置成私密，或者使用更安全的环境变量&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;比如可以这么写&lt;code&gt;config.inc.php&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/** 定义数据库参数 */
$dbHost = getenv(&apos;DB_HOST&apos;);
$dbPort = getenv(&apos;DB_PORT&apos;) ?: &apos;3306&apos;; // 默认端口
$dbUser = getenv(&apos;DB_USER&apos;);
$dbPassword = getenv(&apos;DB_PASSWORD&apos;);
$dbName = getenv(&apos;DB_NAME&apos;);

if ($dbHost &amp;amp;&amp;amp; $dbUser &amp;amp;&amp;amp; $dbPassword &amp;amp;&amp;amp; $dbName) {
    $db = new Typecho_Db(&apos;Pdo_Mysql&apos;, &apos;typecho_&apos;);
    $db-&amp;gt;addServer([
        &apos;host&apos;     =&amp;gt; $dbHost,
        &apos;port&apos;     =&amp;gt; $dbPort,
        &apos;user&apos;     =&amp;gt; $dbUser,
        &apos;password&apos; =&amp;gt; $dbPassword,
        &apos;database&apos; =&amp;gt; $dbName,
        &apos;charset&apos;  =&amp;gt; &apos;utf8mb4&apos;,
    ], Typecho_Db::READ | Typecho_Db::WRITE);

    Typecho_Db::set($db);
} else {
    die(&apos;数据库环境变量未正确配置&apos;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后在vercel平台中配置对应的环境变量即可&lt;/p&gt;
&lt;p&gt;或者觉得配置这么多环境变量麻烦，可以自动解析MySQL地址，只需配置MySQL公共地址即可：
假如你的MySQL地址是
&lt;code&gt;mysql://username:password@host:port/database&lt;/code&gt;
写入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/** 定义数据库参数 */
$databaseUrl = getenv(&apos;DATABASE_URL&apos;);

if ($databaseUrl) {
    $dbParts = parse_url($databaseUrl);

    $dbHost = $dbParts[&apos;host&apos;];
    $dbPort = isset($dbParts[&apos;port&apos;]) ? $dbParts[&apos;port&apos;] : 3306; // MySQL 默认端口
    $dbUser = $dbParts[&apos;user&apos;];
    $dbPassword = $dbParts[&apos;pass&apos;];
    $dbName = ltrim($dbParts[&apos;path&apos;], &apos;/&apos;); // 去掉路径前的 &quot;/&quot;

    $db = new Typecho_Db(&apos;Pdo_Mysql&apos;, &apos;typecho_&apos;);
    $db-&amp;gt;addServer([
        &apos;host&apos;     =&amp;gt; $dbHost,
        &apos;port&apos;     =&amp;gt; $dbPort,
        &apos;user&apos;     =&amp;gt; $dbUser,
        &apos;password&apos; =&amp;gt; $dbPassword,
        &apos;database&apos; =&amp;gt; $dbName,
        &apos;charset&apos;  =&amp;gt; &apos;utf8mb4&apos;,
    ], Typecho_Db::READ | Typecho_Db::WRITE);

    Typecho_Db::set($db);
} else {
    die(&apos;DATABASE_URL 环境变量未配置&apos;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;部署&lt;/h2&gt;
&lt;p&gt;将改动push到项目后，在vercel上连接GitHub，部署项目，vercel会给分配免费的二级域名
访问&lt;code&gt;https://分配的二级域名/install.php&lt;/code&gt;开始初始化安装&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;当然vercel的二级域&lt;code&gt;*.vercel.app&lt;/code&gt;是被墙的，建议使用自己的域名CNAME解析到&lt;code&gt;cname.vercel-dns.com&lt;/code&gt;（不要解析到分配的二级域名），然后在Domains页中添加自己的域名，也可以在&lt;a href=&quot;https://us.kg&quot;&gt;us.kg&lt;/a&gt;上申请免费的域名，托管至cloudflare，可以参考文章&lt;a href=&quot;https://blog.colix.cn/index.php/24.html&quot;&gt;免费域名申请&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;关于主题&lt;/h2&gt;
&lt;p&gt;目前测试下来只有官方预装的两款主题可以正常使用，其他第三方主题无法显示出图片，原因不明
&lt;s&gt;最初看上了Stack主题移植Typecho版，只能泡汤了&lt;/s&gt;&lt;/p&gt;
&lt;h2&gt;结束&lt;/h2&gt;
&lt;p&gt;至此就完成了Typecho在vercel上的部署，可以正常发布文章。当然在serverless上装动态博客总归有些小bug，比如更改外观php页面时不能直接改，需要重新部署，比如不能直接上传图片等等。但是都有办法解决，不影响正常使用
&lt;s&gt;一分没花，要求别这么高&lt;/s&gt;&lt;/p&gt;
</content:encoded><category>杂</category><category>typecho</category></item><item><title>第二届獬豸杯取证复盘</title><link>https://blog.colix.cn/posts/%E5%8F%96%E8%AF%81/xiezhicup_25/</link><guid isPermaLink="true">https://blog.colix.cn/posts/%E5%8F%96%E8%AF%81/xiezhicup_25/</guid><description>更新中，配图未上传</description><pubDate>Sat, 08 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;计算机取证&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;网卡的Mac地址是多少？[标准格式：XX-XX-XX-XX-XX-XX]&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;找到网络驱动器，试一下每个网卡的Mac地址&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;00-0C-29-BF-8B-30&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;系统内部版本号是多少？[标准格式：12345]&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;找到系统信息查看&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;18363&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;计算机系统开机密码是多少？[标准格式：根据实际值填写]&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Windows便签中可以找到（不要去爆破hash了，我以为是弱口令，结果从比赛开始到结束都没爆破出来）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;WAXD9128@&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;分析计算机检材中手机流量包，请问黑客虚拟身份的密码是什么？[标准格式：x123]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分析计算机检材中手机流量包，请问黑客人员使用的夜神模拟器的手机型号是什么？[标准格式：XX-X123X]&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;观察浏览器标识&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;SM-G955N&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;分析计算机检材中手机流量包，请问黑客看视频的时间是几月份？[标准格式：1]&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;我的建议是&lt;s&gt;瞎猜&lt;/s&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;5&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;分析计算机检材中手机流量包，请问“天戮宇宙”出自哪个小说平台？[标准格式：番茄小说网]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;请问在手机模拟器中勒索apk软件的sha256值是什么？[标准格式：全小写]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;接上题，请问勒索apk软件的解锁密码是什么？[标准格式：qwer.com]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;signed_xz.exe程序SHA1后6位是多少？[标准格式：524c62]&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;找到&lt;code&gt;setup_share_game_signed_xz.exe&lt;/code&gt;，算一下&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;8955b1&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;signed_xz.exe程序中的函数名为curl_version_info的函数地址是多少？[标准格式：0c6875c2]&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;上题的文件，丢IDA（不要忘记0x，&lt;s&gt;我倒腾了半天居然是没加0x&lt;/s&gt;）
&lt;img src=&quot;https://blog.colix.cn/_astro/1616933018.D9K0JaWs_1maRSV.webp&quot; alt=&quot;2025-04-02T11:51:33.png&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;0x4393c0&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;signed_xz.exe程序中节名为.reloc的虚拟地址是多少？[标准格式：0c526n5624]&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;丢die
&lt;img src=&quot;https://blog.colix.cn/_astro/3078908350.oug3pIKg_Z102cHg.webp&quot; alt=&quot;2025-04-02T11:52:20.png&quot; /&gt;
&lt;code&gt;0x035b5000&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;请分析检材中澳门新葡京APK其包名是？[标准格式：com.abcd.xxx]&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;找找，瞪眼法&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;com.suijideszzuiji.cocosandroid&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;请分析检材中澳门新葡京APK是否加固，加固则说明是什么加固？[标准格式：360加固宝或未加固]&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;瞪眼法（猜的未加固，还真是）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;未加固&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;请分析检材中澳门新葡京APK是否会往手机的SD卡中写入数据，则该权限的名称是？[标准格式：android.xx.xxx]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;请分析检材中澳门新葡京APK登录的api地址。[标准格式：https://www.baidu.com/api/login]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;请分析检材中澳门新葡京APK其中关于腾讯运营商的服务留存了QQ号是？[标准格式：123456790]&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;请分析Navicat中root用户的密码是什么？[标准格式：@123Aa]&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h1&gt;服务器取证&lt;/h1&gt;
&lt;p&gt;待完善&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;手机取证&lt;/h1&gt;
&lt;p&gt;待完善&lt;/p&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;第一次打正式比赛，赛前准备是不够充足的，主要是工具的使用，用平航手机取证没能打开手机镜像，又临时下了美亚的取证工具才解决，使用也不熟练（赛后复盘使用了火眼）。计算机部分更多还是对工具的掌握，手机则是对安卓系统的一定了解，服务器取证应该更难一些，需要熟练掌握命令以及服务器常用软件的熟知。第一次个人赛打的是比较艰难的，后续的团队赛希望可以配合打好&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>取证</category></item><item><title>Vercel😉umami</title><link>https://blog.colix.cn/posts/sundry/vercel_umami/</link><guid isPermaLink="true">https://blog.colix.cn/posts/sundry/vercel_umami/</guid><description>非常实用的开源访问统计项目</description><pubDate>Mon, 06 Jan 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Umami&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;作为一款在github上有23k+Star的开源统计项目，umami广泛用于统计网站访问数据，并且可以自托管，保护隐私&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;demo可见本站&amp;lt;a href=&quot;https://umami.colix.cn/share/QzOJnDTlwBLFFzdQ/blog.colix.cn&quot;&amp;gt;『访问统计』&amp;lt;/a&amp;gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;部署&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;项目官方提供免费的服务，注册即可以使用，如果注重隐私，可以选择托管至vercel（官方提供的数据存储在us或欧洲的服务器上，并且免费版本数据只保存六个月，限制网站数量三个）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;部署很简单，在github打开&lt;a href=&quot;https://github.com/umami-software/umami&quot;&gt;umami项目官网&lt;/a&gt;后fork至自己的仓库，在vercel创建数据库
&lt;img src=&quot;https://blog.colix.cn/_astro/1417981062.AlGx9i7y_hc2RB.webp&quot; alt=&quot;选这个&quot; /&gt;
连接数据库有两种方式&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;可以直接在环境变量中添加&lt;code&gt;key&lt;/code&gt;的值为&lt;code&gt;DATABASE_URL&lt;/code&gt;,&lt;code&gt;value&lt;/code&gt;的值为你的数据库地址&lt;/li&gt;
&lt;li&gt;在项目创建完成后选择&lt;code&gt;connect&lt;/code&gt;你的数据库&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;等待部署完成&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;使用&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;部署完成后访问vercel提供的页面地址，设置账号密码后登录&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在设置中添加网站，设置名称和域名
&lt;img src=&quot;https://blog.colix.cn/_astro/1909770734.DB9oPos9_2pv4YM.webp&quot; alt=&quot;添加网站&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;选择跟踪代码
&lt;img src=&quot;https://blog.colix.cn/_astro/884781463.CtcNwqQn_Zk2xv.webp&quot; alt=&quot;跟踪代码&quot; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;将下面提供的script脚本嵌入到你需要统计的页面的&lt;code&gt;&amp;lt;head&amp;gt;跟踪代码&amp;lt;/head&amp;gt;&lt;/code&gt;之间，即可开始统计&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;共享统计数据&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;启用共享链接
&lt;img src=&quot;https://blog.colix.cn/_astro/802638506.CoaXBaJP_Z28rzwc.webp&quot; alt=&quot;开启共享链接&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里会提供公开可见的访问数据统计查看连接&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;至此完成部署，Enjoy it~&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>杂</category><category>umami</category></item><item><title>Vercel部署Blinko(尝试中)</title><link>https://blog.colix.cn/posts/sundry/vercel_blinko/</link><guid isPermaLink="true">https://blog.colix.cn/posts/sundry/vercel_blinko/</guid><description>尝试将Blinko托管至Vercel</description><pubDate>Sun, 29 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Blinko&lt;/h2&gt;
&lt;p&gt;Blinko是一款我一直在用的自托管笔记平台，目前应该没有memos那么有名，但是其功能丰富，轻量（程序本体加数据库空间也只占用300m左右，虽然远不及memos，但是功能和资源占用总得有取舍🤷‍♂️），UI设计也非常友好，并且可以配合AI使用，功能更强大（需要API）。Blinko可以将闪念或笔记公开实现类似memos广场的效果。
&lt;a href=&quot;https://blinko.colix.cn/share/rj1blane&quot;&gt;我的Blinko&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.colix.cn/_astro/1174206848.DFHtwGoo_UpLr6.webp&quot; alt=&quot;Blinko&quot; /&gt;
附上&lt;a href=&quot;https://github.com/blinko-space/blinko&quot;&gt;Github链接&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;部署&lt;/h2&gt;
&lt;p&gt;官方页面给出的部署方式是docker容器(也是我目前在用的方式)，这样部署只需要pull一下镜像或者直接使用官方给的脚本即可&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -s https://raw.githubusercontent.com/blinko-space/blinko/main/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但是官方的demo是放在vercel上的？&lt;img src=&quot;https://blog.colix.cn/_astro/3470816038.eB35yEAp_aXXLf.webp&quot; alt=&quot;demo链接&quot; /&gt;
&lt;a href=&quot;https://blinko-demo.vercel.app/&quot;&gt;官方demo&lt;/a&gt;
&lt;em&gt;&lt;s&gt;为了白嫖&lt;/s&gt;&lt;/em&gt; 为了给服务器减减负，我决定大胆尝试一手&lt;/p&gt;
&lt;h2&gt;Trying&lt;/h2&gt;
&lt;p&gt;我在网上没有找到相关的教程可以抄作业，只能自己动手😶‍🌫️
首先在vercel创建postgres数据库（其他博主都说有postgres这个选项，但是我在storage里并没有找到这个，只找到叫Neon的Serverless postgres，原因不明🤔）
vercel部署docker需要在&lt;code&gt;next.config.js&lt;/code&gt;文件中加入如下代码添加docker支持&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// next.config.js
module.exports = {
  // ... rest of the configuration.
  output: &quot;standalone&quot;,
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当我去配置&lt;code&gt;next.config.js&lt;/code&gt;文件时候发现已经存在这段代码了，并且也许作者本就是设计了将Blinko丢到vercel上？(如图)&lt;img src=&quot;https://blog.colix.cn/_astro/2363932397.DQ6OPB_4_Z2iNlHp.webp&quot; alt=&quot;判断是否是vercel？&quot; /&gt;
既然如此，将Blinko项目fork之后，就直接在vercel导入，这时候部署是会失败的，因为还没有连接数据库。将数据库连接到项目之后再次部署，提示成功，Blinko主页可以正常打开（如图）。
Blinko并没有默认用户，使用前是需要先注册一个用户的，将注册的第一个用户作为管理员，注册完第一个用户就会默认关闭注册（虽然但是貌似有一个bug，即使设置禁止注册，直接访问&lt;code&gt;/signup&lt;/code&gt;页面还是可以注册，提交bug后作者在0.31.9版本已经修复这个问题）
&lt;img src=&quot;https://blog.colix.cn/_astro/3534171785.CvfIcNa0_1odTNg.webp&quot; alt=&quot;登录页&quot; /&gt;&lt;/p&gt;
&lt;p&gt;但是登陆的时候就开始出bug了&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.colix.cn/_astro/2224595226.BGrgiBJ4_ZbryR5.webp&quot; alt=&quot;提示服务器错误&quot; /&gt;&lt;/p&gt;
&lt;p&gt;访问注册页同样正常，但是注册的时候会提示已经设置成禁止注册（？？？这时候设置生效了？？？）&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.colix.cn/_astro/1713104548.C1TTcDLq_Z1AmX46.webp&quot; alt=&quot;禁 止 注 册&quot; /&gt;&lt;/p&gt;
&lt;p&gt;也许是数据库的问题？数据库应该是连接成功的，storage页可以看到数据库已经有占用一定的空间&lt;/p&gt;
&lt;p&gt;问题解决中……&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;作者回复&lt;/h2&gt;
&lt;p&gt;作者回复关于注册bug时说不推荐vercel部署（在vercel上程序确实是没有写权限的，只能连接数据库，也许我应该自己改改……）
&lt;img src=&quot;https://blog.colix.cn/_astro/2982561518.zjk7t-b3_7Nqgb.webp&quot; alt=&quot;作者回复&quot; /&gt;&lt;/p&gt;
&lt;p&gt;🤔🤔🤔&lt;/p&gt;
</content:encoded><category>杂</category><category>建站</category></item></channel></rss>