生活分享

在 VPS 上自架 AI 服務:Ollama+Open WebUI

自架 AI 只要一台 Linux VPS:把 Ollama 與 Open WebUI 架成自己或小團隊專用的服務,Ollama 用官方腳本裝成服務,Open WebUI 用 Docker 跑起來只綁 127.0.0.1,前面用 Caddy 或 Nginx 開 HTTPS。這篇照官方文件寫指令、環境變數、反向代理、關閉註冊與防火牆,說明為什麼 11434 埠不能對外,並交代備份、更新與費用。

更新日期: 閱讀時間約 11 分鐘

插圖:一台筆電經過一把鎖連到一台伺服器主機,代表加密連線到自己的機器。
圖片:Mokaair (© Mokaair)

把 Ollama 裝在自己的筆電上,只有坐在那台電腦前面才用得到。換成一台 Linux VPS,同一組工具就變成一個隨時開著、手機和公司電腦都連得上的服務:Ollama 負責跑模型,Open WebUI 負責介面與帳號,前面再放一台反向代理接上網域與 HTTPS。結論先講:指令都是現成的,真正要小心的是把埠關好,因為 Ollama 的本機 API 不需要任何驗證,這一點決定了整台機器的設定方式。搜「」的人,重點不在指令,在把埠關好。

這篇帶你把六件事做完:挑機器規格、用官方腳本裝 Ollama 並改 systemd 的環境變數、用 Docker 跑 Open WebUI 並只綁在 127.0.0.1、用 Caddy 或 Nginx 加 Certbot 開 HTTPS、開好帳號與防火牆、安排備份與更新,最後把費用結構列清楚。租機器、設定網域 DNS、連 SSH 這些基礎步驟站上已經有一篇完整教學,照那篇做,這裡只補 服務的部分。

先決定機器:CPU、顯示卡與硬碟

Ollama 在 Linux 上支援 Nvidia 與 AMD 的顯示卡:官方硬體支援頁寫 Nvidia 需要 compute capability 5.0 以上、驅動 550 以上,5.0 到 6.2 的卡則需要 570 以上,AMD 則需要 ROCm v7 的驅動,支援型號同一頁都列了。問題是一般 VPS 方案多半沒有顯示卡,模型會整顆跑在 CPU 與系統記憶體上。官方文件沒有給「幾核心、幾 GB 記憶體可以跑哪個模型、每秒幾個 token」的對照表,速度以官網與你自己實測為準,不要照來路不明的表格下單。

能先算清楚的是空間。Ollama 模型庫每個模型的 tags 頁都標了檔案大小,例如 llama3.2:1b 是 1.3GB、llama3.2:3b 是 2.0GB,兩個的上下文視窗都標 128K。模型下載後放在 /usr/share/ollama/.ollama/models,想換位置就設 OLLAMA_MODELS,並照官方註記把目錄的擁有者改成 ollama 這個使用者。另外 Ollama 預設的上下文視窗是 4096 個 token,要調大就設 OLLAMA_CONTEXT_LENGTH,但文件同時提醒:上下文開得越大,需要的記憶體越多。

  • 純 CPU 的方案:先用 1B 到 3B 這種小模型測,記憶體要放得下模型檔加上下文;官方沒有對照表,能不能接受以你實際試出來的速度為準。
  • 有顯示卡的方案:照官方硬體支援頁對型號與驅動版本。Ollama 會依顯示記憶體決定預設上下文,小於 24 GiB 是 4k、24 到 48 GiB 是 32k、48 GiB 以上是 256k。
  • 硬碟:模型檔之外還要放 Docker 映像檔,Open WebUI 官方文件寫 amd64 的標準映像檔下載約 1.8GB、slim 版約 1.5GB。
  • 人多就更吃記憶體:官方 FAQ 寫同一個模型的並行請求會把上下文乘上請求數,記憶體不夠時新請求會排隊,塞太多會回 503。

裝 Ollama:安裝腳本、systemd 與環境變數

官方 Linux 安裝頁給的就是一行安裝腳本。跑完會建立一個 ollama 系統使用者,並把 Ollama 設成 systemd 服務(同一頁的解除安裝步驟就是停掉這個服務、刪掉服務檔,再把 ollama 使用者移除),所以之後的操作都是 systemctl 與 journalctl。

裝 Ollama 並確認服務跑起來(照 docs.ollama.com 的 Linux 頁) · bash
curl -fsSL https://ollama.com/install.sh | sh   # 官方安裝腳本
ollama -v                                       # 確認版本
sudo systemctl status ollama                    # 看服務狀態
ollama pull llama3.2:3b                         # 先拉一個小模型
journalctl -e -u ollama                         # 服務日誌

環境變數不能寫在你自己的 shell 設定檔裡,因為服務是以 ollama 這個使用者在跑。官方 FAQ 的做法是執行 systemctl edit ollama.service,在 [Service] 區段底下加 Environment 行,存檔後重新載入 systemd 再重啟。VPS 上最常加的一行是 OLLAMA_HOST。Ollama 預設只綁 127.0.0.1 的 11434 埠,而 Open WebUI 跑在 Docker 容器裡算是另一個網路介面,所以 Open WebUI 的疑難排解頁直接要你把 OLLAMA_HOST 設成 0.0.0.0 讓它聽所有介面。這一改,防火牆就從「建議」變成「必要」。

systemctl edit ollama.service 的覆寫內容(照官方 FAQ 的 Linux 段) · text
# sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_CONTEXT_LENGTH=8192"

# 存檔離開後,照文件再跑這兩行:
# sudo systemctl daemon-reload
# sudo systemctl restart ollama

裝 Open WebUI:Docker Compose 只綁 127.0.0.1

Docker 照官方文件用 apt 儲存庫裝(Open WebUI 的 Caddy 教學也是這樣做),要裝的套件是 docker-ce、docker-ce-cli、containerd.io、docker-buildx-plugin 與 docker-compose-plugin,最後一個提供的就是中間有空格的 docker compose 指令;舊教學裡帶連字號的寫法是第一版語法,官方文件要你用第二版。

Open WebUI 官方快速開始給的是一行 docker run,把容器內部的 8080 對應到主機的 3000。在 VPS 上要改一個地方:Docker 官方文件講得很白,發佈埠預設是不安全的,埠一發佈就不只主機看得到,外面也看得到;在發佈時加上 127.0.0.1,就只有這台主機連得進去。反向代理跟容器在同一台機器上,所以 3000 只留給本機就夠。

docker-compose.yml(官方快速開始的 Compose 版本,埠改成只綁本機) · yaml
services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    ports:
      - "127.0.0.1:3000:8080"
    volumes:
      - open-webui:/app/backend/data
    extra_hosts:
      - host.docker.internal:host-gateway
    environment:
      - WEBUI_SECRET_KEY=這裡貼 openssl rand -hex 32 的輸出
      - OLLAMA_BASE_URL=http://host.docker.internal:11434
      - WEBUI_URL=https://chat.example.com
      - WEBUI_SESSION_COOKIE_SECURE=true
    restart: unless-stopped

volumes:
  open-webui:

存好之後在同一個目錄執行 docker compose up -d。幾個欄位官方文件都有交代:WEBUI_SECRET_KEY 用 openssl rand -hex 32 產生並固定下來,容器重建時才不會把所有人登出,它同時用來簽發登入 token 與加密存放的敏感資料;volume 是對話、帳號、設定與上傳檔案的所在,文件的原話是絕對不要不掛 volume 就跑;OLLAMA_BASE_URL 在 Docker 裡的預設值本來就是 host.docker.internal 的 11434 埠,extra_hosts 那行讓容器找得到主機;WEBUI_URL 填公開網址,OAuth 與內部連結才會正確。介面的操作步驟以官網當天版本為準。

反向代理與 HTTPS:Caddy 或 Nginx 加 Certbot

Open WebUI 自己不處理 TLS,官方文件直接寫要放在反向代理後面由代理負責 HTTPS。同一頁列了四件跟代理有關的設定:WEBUI_URL 填公開網址、CORS_ALLOW_ORIGIN 要對得上公開網址(不然 WebSocket 會安靜地連不上)、關掉代理的緩衝(串流回應需要)、把讀取逾時至少拉到 300 秒,因為模型回一段長文可能要好幾分鐘。

Caddy 是最省事的一條路。官方的 Debian 與 Ubuntu 套件裝完會自動以名為 caddy 的 systemd 服務啟動,設定檔在 /etc/caddy/Caddyfile,寫上網域再加一行 reverse_proxy 就結束了。Caddy 會自己去 Let's Encrypt 或 ZeroSSL 這類公開 ACME 憑證機構取得憑證、自動續期,並把 HTTP(預設埠 80)轉到 HTTPS(預設埠 443)。前提是網域的 A 記錄已經指向這台機器,而且 80 與 443 從外面連得到。改完設定用 systemctl reload caddy 重新載入,官方文件特別說不要用 stop,那會造成停機。

Caddyfile:一行反向代理(照 Open WebUI 官方 Caddy 頁,埠換成本機的 3000) · text
# /etc/caddy/Caddyfile
chat.example.com {
	reverse_proxy 127.0.0.1:3000
}

機器上已經在跑 Nginx 就走另一條:照 Open WebUI 的 Nginx 頁,一個 server 區塊聽 80,把 /.well-known/acme-challenge/ 留給憑證驗證、其他路徑 301 轉到 HTTPS;另一個聽 443 的區塊用 proxy_pass 指到 Open WebUI,帶上 proxy_http_version 1.1 與 Upgrade、Connection 標頭讓 WebSocket 過得去,加上 proxy_buffering off,並把 proxy_read_timeout 拉長,官方範例用的是 1800 秒。憑證交給 Certbot:官方指示是用 snap 安裝,再跑 certbot 的 nginx 模式,它會自動改好設定並裝上憑證。

Let's Encrypt 官方說明憑證預設效期是 90 天,建議每 60 天續一次,而且不收費;Certbot 安裝時會附上 cron 或 systemd timer 自動續期,你只要跑一次演練指令確認它會動就好。防火牆也在這一步一起設:Ubuntu 官方文件的預設工具是 ufw,它一開始是關閉的,要自己打開。順序是先放行 22 再打開防火牆,反過來很容易把自己鎖在門外。

Certbot 與 ufw:憑證自動續期,防火牆只留三個埠 · bash
# Certbot:官方建議的 snap 安裝方式
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
sudo certbot --nginx          # 取得憑證並自動改 Nginx 設定
sudo certbot renew --dry-run  # 演練自動續期

# 防火牆:先放行 SSH,再打開
sudo ufw allow 22
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
sudo ufw status

四段路的架構圖:使用者經 HTTPS 連到反向代理,代理轉給只綁本機的 Open WebUI,Open WebUI 再連到主機上的 Ollama。
從左到右看:只有反向代理站在公開網路上,後面兩段都留在這台機器裡面,下排是防火牆與備份的原則。 · 圖片:Mokaair (© Mokaair)
閱讀完整文字說明

由左到右的四格架構圖。第一格是使用者,用瀏覽器或手機連線,對外只開 443 埠。往右的箭頭標著 HTTPS 443,連到第二格反向代理,由 Caddy 或 Nginx 擔任,會把 80 自動轉到 443,憑證 90 天自動續期。第二格往右的箭頭標著 127.0.0.1 冒號 3000,連到第三格 Open WebUI,容器內部埠是 8080,只發佈到 127.0.0.1 的 3000 埠,帳號與對話存在 volume 裡。第三格往右的箭頭標著 11434 埠,連到第四格 Ollama,它是 systemd 服務,環境變數 OLLAMA_HOST 設為 0.0.0.0 冒號 11434,模型檔放在主機硬碟。圖的下排有兩個提醒框:左邊是防火牆,ufw 只放行 22、80、443,11434 不對外因為本機 API 不需要驗證,而且 Docker 發佈埠會繞過 ufw,所以埠要綁 127.0.0.1;右邊是備份與更新,資料在 volume 裡,更新只換映像檔,更新前把 volume 打包成 tar.gz,備份檔要複製到這台機器以外的地方。

帳號、關閉註冊與防火牆

第一個註冊的帳號就是管理員,之後 Open WebUI 會自動把註冊關掉,這一步不用自己動手;新帳號的預設角色是 pending,要管理員核准才看得到東西。要讓同事自己註冊就把 ENABLE_SIGNUP 設成 true,但把 DEFAULT_USER_ROLE 留在 pending。要注意這兩個都是會寫進資料庫的設定,官方叫它 ConfigVar,第一次啟動之後再改環境變數不一定生效,官方建議直接在管理面板改。共用的機器還可以把登入 token 的效期縮短,JWT_EXPIRES_IN 預設是四週。

防火牆是這整篇最重要的一步。Ollama 的 API 文件第一句話就是:在本機透過 11434 埠存取 API 不需要任何驗證。換句話說,那個埠只要對外開著,任何掃到你 IP 的人都能用你的機器跑模型。VPS 上只開 22、80、443,其他一律不開。還有一個容易中招的地方:Docker 官方文件寫明 Docker 與 ufw 的規則互不相容,容器發佈埠的流量走 nat 表,在抵達 ufw 使用的 INPUT 與 OUTPUT 鏈之前就被轉走,等於繞過你的防火牆設定。這就是上面把埠寫成只綁 127.0.0.1 的原因:不要指望用 ufw 擋容器的埠,一開始就不要把它發佈到公開介面。

備份、更新與費用結構

資料不在容器裡,在 volume 裡:對話、使用者、設定、上傳的檔案都在那裡。官方備份做法是開一個臨時的 alpine 容器,把整個 volume 打包成 tar.gz,每次更新前做一次,平常照使用頻率定期做。還原指令會先清空 volume 再解開備份檔,執行前務必確認拿的是對的檔案。VPS 上要多做一件事:把備份檔複製到這台機器以外的地方,不然機器整台掛掉時備份也一起沒了。

備份 volume 與更新兩個服務(照各自官方文件) · bash
# 備份 Open WebUI 的 volume(官方更新指南的做法)
docker run --rm -v open-webui:/data -v $(pwd):/backup \
  alpine tar czf /backup/openwebui-$(date +%Y%m%d).tar.gz /data

# 更新 Open WebUI:換映像檔,volume 不動
docker compose pull
docker compose up -d

# 更新 Ollama:再跑一次安裝腳本
curl -fsSL https://ollama.com/install.sh | sh

更新 Open WebUI 就是把容器換成新的映像檔,資料原封不動。官方對多人共用或正式環境的建議是釘一個版本標籤而不是跟著 main 走,升級前先看發行說明、先備份,因為含資料庫遷移的版本是單向的,很難退回去。Ollama 的更新是再跑一次安裝腳本。

在 VPS 上架 Ollama 與 Open WebUI 的十個步驟,指令與變數名稱來自各專案官方文件,2026 年 9 月查證。
步驟指令或設定備註
裝 Ollamacurl -fsSL https://ollama.com/install.sh | sh官方 Linux 安裝腳本,裝完是名為 ollama 的 systemd 服務
改 Ollama 設定systemctl edit ollama.service,在 [Service] 加 Environment 行常加 OLLAMA_HOST 與 OLLAMA_CONTEXT_LENGTH,改完 daemon-reload 再 restart
裝 Docker照官方 apt 儲存庫裝 docker-ce 等五個套件docker-compose-plugin 提供中間有空格的 docker compose 指令
跑 Open WebUIports 寫 127.0.0.1:3000:8080,volume 掛 open-webui:/app/backend/data發佈埠預設對外開放,加上本機位址才只有這台機器連得到
設定祕鑰WEBUI_SECRET_KEY 填 openssl rand -hex 32 的輸出不固定的話,容器一重建就把所有人登出
反向代理Caddyfile 裡一行 reverse_proxy 127.0.0.1:3000Caddy 自動取得與續期憑證,並把 80 轉到 443
憑證(Nginx 路線)sudo certbot --nginx,再跑 sudo certbot renew --dry-runLet's Encrypt 憑證 90 天,安裝時附的 cron 或 timer 會自動續
帳號與註冊第一個帳號自動成為管理員;ENABLE_SIGNUP 與 DEFAULT_USER_ROLE兩個都是 ConfigVar,第一次啟動後建議在管理面板改
防火牆ufw allow 22 與 80 與 443,再 ufw enable11434 不對外;Docker 發佈埠會繞過 ufw,所以埠綁本機
備份用臨時 alpine 容器把 volume 打包成 tar.gz更新前一定先做;還原會先清空 volume

費用結構跟雲端 API 完全不同:你付的是機器,不是 token。固定支出是 VPS 月費(看規格,價格以主機商官網為準,這篇不列特定業者的數字)、網域年費,再加上放備份的空間;憑證從 Let's Encrypt 拿不用錢,Ollama 與 Open WebUI 本身也不用錢。會變動的是流量,以及你願不願意為了速度升級到有顯示卡的方案。要判斷划不划算,就拿這幾項跟你現在每個月付的訂閱或 API 帳單擺在一起比。

最後提醒一件常被忽略的事:自架之後,這台機器的更新、備份、憑證、帳號與資料外洩風險都算你的。同一件事交給雲端服務商,責任分界不一樣;決定之前先想清楚你接得住哪些。模型要挑哪一個、蒸餾版和完整版差在哪,站上另有專文可以接著看。

  • 生活分享

    Claude Code、Codex 搭本機模型:兩種接法怎麼選

    Claude Code 與 Codex 搭配本機模型有兩種接法:代理照常連雲端、把大量雜務交給腳本或 MCP 工具去問本機模型,或是把代理的模型整個換成本機模型。這篇用資料能不能出門、上下文開得夠不夠長、工作的類型三個問題幫你選,並對照 Ollama、LM Studio、Anthropic 與 OpenAI 的官方文件,分清楚本機權重、Ollama 的 cloud 標籤與供應商端點是三種不同的東西。

  • 生活分享

    把本機模型包成 MCP 工具,Claude Code 與 Codex 共用一支伺服器

    用官方 Python SDK 寫一支 stdio 的 MCP 伺服器,把本機的 Ollama 模型包成工具,Claude Code 與 Codex 就能共用:工具只收 inbox 底下的路徑,只回分類結果與結果檔路徑,不回信件原文。文中列出兩邊的登記指令、逾時與輸出上限的官方預設值,以及換成別家本機模型只改環境變數 LOCAL_MODEL 的做法,步驟都來自官方文件。

  • 生活分享

    把 Claude Code、Codex 整個換成本機模型:Ollama 與 LM Studio 設定與還原

    Ollama、LM Studio 與 Codex 的文件寫了把 Claude Code、Codex 整個換成本機模型的接法:Ollama 用 ollama launch 一行指令或手動設定,LM Studio 先開本機伺服器再設環境變數或加 --oss。這篇把四種組合的指令、兩家文件建議的上下文長度、Claude Code 用 /status 確認連到誰的方法,以及用完怎麼還原整理在一起;需要先裝好 Ollama 或 LM Studio,並且已有 Claude Code 或 Codex。

  • 生活分享

    Claude Code、Codex 搭本機模型的注意事項:開工前的檢查清單

    Claude Code 或 Codex 搭本機模型之前,先照一張表逐項核對:代理讀不讀得到原始檔、現在連的是誰、標籤是不是 :cloud、上下文實際開多長、逾時與輸出量、怎麼驗收。每一項寫怎麼檢查,並指出詳見同組哪一篇,另外收進供應商端點、條款與授權、繁體中文用字檢查;檢查方法取自 Anthropic、OpenAI、Ollama 與 DeepSeek 的官方文件。

最新旅遊情報攻略

資料來源

生活分享