生活分享

把 AI 幫你寫的網站放上網:VPS、網域與 HTTPS 一次搞定

AI 幫你生出網站之後,最後一哩是放到自己的機器上。這篇走完通用流程:挑 VPS、用 SSH 金鑰登入並關掉密碼登入、開 ufw 與自動更新、用 rsync 或 git clone 送檔案、靜態站用 Caddy 或 Nginx 加 certbot 開 HTTPS、應用程式交給 systemd 跑並由反向代理轉發、設好 A 與 AAAA 記錄與 TTL,最後照檢查清單驗收。

閱讀時間約 7 分鐘

插圖:左邊一個資料夾圖形沿著一條路徑連到中間的伺服器方塊,右邊是一個鎖頭與代表網域的圓形,下方有一行短標題
圖片:Mokaair (© Mokaair)

幫你把網站做出來之後,剩下的不是寫程式,是搬家:把檔案放到一台永遠開著的機器上,讓網域指過去,再讓瀏覽器願意顯示那個鎖頭。三件事都有標準做法,走過一次,下一個專案照抄。

這篇是通用流程,不綁主機商也不列價格:方案、地區與快照收費各家不同,以各家官網為準。從挑 VPS 走到 DNS 記錄與上線驗收,每一步都附一段可以交給 的提示詞。指令讓它寫,按下 Enter 的人是你。

先分清楚你要放的是哪一種網站

先看一眼 AI 給你的資料夾。點兩下 index.html 就看得到畫面,那是靜態網站,伺服器只要把檔案原樣送出去。如果要先啟動一個程式、它會監聽某個連接埠才有畫面,那是應用程式。

差別只在中段:應用程式需要一個常駐服務,再由前面的網頁伺服器把請求轉進去。其餘步驟兩種完全一樣。

  • 靜態網站:只有 HTML、CSS、JavaScript 與圖片,沒有要啟動的程式。
  • 應用程式:有 package.json(Node.js)或 requirements.txt(Python)。
  • 分不出來,就把檔案清單貼給 AI,請它判斷並說出理由。

選 VPS:先看四個通用條件

VPS 是一台租來的 Linux 虛擬機,你拿到管理者權限,也接下更新與備份的責任。各家的方案、地區與快照收費差很多,這篇不點名任何一家,只列四個條件,規格與費用以各家官網為準。

  • 機房地區:讀者主要在台灣,就從台灣、日本、新加坡挑,來回延遲摸得出來。
  • 記憶體:靜態網站需求很低,應用程式會吃掉不少,以專案官方文件的最低需求為準。
  • 作業系統:選 Ubuntu LTS,每兩年一版、有五年標準安全維護,目前最新是 26.04 LTS。
  • 快照與備份:確認能不能建快照、能不能排程、要不要加錢。能還原,你才敢動設定。

第一次登入就把門鎖好

新機器上線幾分鐘就會有人來試密碼,所以第一次登入要做的不是佈署,是加固。順序不能顛倒:先產生金鑰、建立一般使用者、把公開金鑰送上去,確認登得進來才關掉密碼登入,最後開防火牆與自動安全更新。

金鑰用 ssh-keygen 產生,私鑰留在自己的電腦、絕對不上傳。Ubuntu 官方文件寫著 root 帳號預設被停用,日常操作一律用一般使用者加 sudo。

在自己的電腦產生金鑰,在伺服器建立一般使用者,再把公開金鑰送上去 · bash
# 在你自己的電腦上執行:產生一把金鑰,私鑰留在本機
ssh-keygen -t ed25519 -C "my-laptop"

# 用主機商給的帳號登入伺服器,建立一般使用者並加入 sudo 群組
sudo adduser deploy
sudo adduser deploy sudo

# 回到自己的電腦,把公開金鑰送上去,再用新帳號登入試一次
ssh-copy-id deploy@203.0.113.10
ssh deploy@203.0.113.10

確認新帳號用金鑰進得去、也能 sudo,再動 SSH 設定。設定檔在 /etc/ssh/sshd_config,預設會載入 /etc/ssh/sshd_config.d/ 底下的 .conf 檔,OpenSSH 取第一個讀到的值,新增一個檔案比改主檔保險。手冊記載 PasswordAuthentication 預設是 yes。

新增 /etc/ssh/sshd_config.d/99-hardening.conf,關掉密碼登入與 root 登入 · text
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin no

改完先用 sshd -t 驗證語法再重啟,原本的視窗不要關,另開一個視窗測登入。防火牆用 ufw,它的手冊寫著安裝後預設關閉、進入方向預設拒絕,也提醒啟用時可能切斷現有連線,先放行 SSH 再啟用。

檢查設定、重啟 ssh,再開防火牆與自動安全更新 · bash
# 先驗證語法,確認沒問題再重啟;原本的視窗留著不要關
sudo sshd -t
sudo systemctl restart ssh.service

# 防火牆:先放行 SSH,再放行網站要用的兩個連接埠,最後才啟用
sudo ufw default deny incoming
sudo ufw allow 22
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enable
sudo ufw status verbose

# 自動安全更新
sudo apt update
sudo apt install unattended-upgrades
sudo unattended-upgrade -v --dry-run

自動安全更新交給 unattended-upgrades。Ubuntu 文件說明,行為寫在 /etc/apt/apt.conf.d/ 的 50unattended-upgrades,開關寫在同一層的 20auto-upgrades,設成 1 就是每天執行。

把檔案送上去:rsync 或 git clone

兩種做法。rsync 把資料夾同步上去,手冊裡 -a 是封存模式(等於 -rlptgoD)、-v 顯示過程、-z 傳輸時壓縮;--delete 會刪掉目的地多出來的檔案,容易誤刪,第一次先不要加。git clone 要專案已經推上 Git 服務,之後更新只要 git pull。

把檔案送上去:rsync 同步資料夾,或在伺服器上取回專案 · bash
# 做法一:從自己的電腦同步整個資料夾(第一次先不要加 --delete)
rsync -avz ~/site/ deploy@203.0.113.10:/var/www/site/

# 做法二:在伺服器上取回專案,之後更新只要 git pull
sudo apt install git
git clone https://example.com/you/your-site.git /var/www/site

rsync 只傳有變動的部分,git 讓你知道線上跑的是哪一版。

靜態網站:Caddy 幾行設定,或 Nginx 加 certbot

靜態網站只需要一個把檔案送出去的伺服器,加上 HTTPS。最省事的是 Caddy:官方文件寫明,它預設就用 HTTPS 提供服務、自動取得並續發憑證,也會把連接埠 80 的 HTTP 自動轉到連接埠 443,預設啟用 Let's Encrypt 與 ZeroSSL 兩家憑證機構。設定檔在 /etc/caddy/Caddyfile。

/etc/caddy/Caddyfile:上面是靜態網站,下面是把請求轉給本機的應用程式 · text
# 靜態網站:把檔案原樣送出去
example.com {
    root * /var/www/site
    file_server
}

# 應用程式:轉給只監聽本機的服務
app.example.com {
    reverse_proxy 127.0.0.1:3000
}

另一條路是 Nginx 加 certbot。Nginx 用 server 與 location 區塊,root 指到檔案目錄;certbot 官方指示是用 snap 安裝,再執行 certbot --nginx,它會改好設定並取得憑證,憑證放在 /etc/letsencrypt/live/ 底下。

另一條路:Nginx 加 certbot,憑證由 certbot 取得與續發 · bash
sudo apt install nginx
# 在 /etc/nginx/ 底下的站台設定裡,用 server 與 location 指到檔案目錄
#   server { server_name example.com; location / { root /var/www/site; } }
sudo nginx -t

# certbot 官方指示:先移除舊套件,再用 snap 安裝
sudo apt-get remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot

# 取得憑證,certbot 會順手改好 Nginx 設定,最後演練一次續發
sudo certbot --nginx
sudo certbot renew --dry-run

憑證不是設一次就沒事。Let's Encrypt 說明,預設憑證效期 90 天、建議每 60 天續發一次,另有需要自己選用的短期憑證,效期 6 天。certbot 從 4.0.0 版起在剩餘效期不到三分之一時續發,安裝時就裝好排程。Caddy 也會自動續發,官方頁沒寫明提前幾天,以官網為準。

應用程式:systemd 顧著跑,反向代理轉進去

應用程式在終端機裡跑起來,關掉連線就停了,所以交給 systemd 管:寫一個服務單元檔,說明執行什麼指令、用哪個使用者、在哪個目錄、掛掉要不要重啟。systemd 文件寫著,只設 ExecStart 時 Type 預設是 simple、Restart 預設是 no,要它自己爬起來就寫 on-failure。

/etc/systemd/system/mysite.service:讓應用程式開機自動啟動、掛掉自動重啟 · text
[Unit]
Description=My AI-built site
After=network.target

[Service]
Type=simple
User=deploy
WorkingDirectory=/home/deploy/app
Environment=PORT=3000
ExecStart=/usr/bin/node /home/deploy/app/server.js
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

# 存檔後執行:
#   sudo systemctl daemon-reload
#   sudo systemctl enable --now mysite
#   systemctl status mysite

讓應用程式只監聽本機,外面連不到它,只有前面的網頁伺服器轉得進去:Caddy 用 reverse_proxy,Nginx 在 location 區塊用 proxy_pass,憑證與轉址都由前面那一層處理。

網域指過來:A、AAAA 記錄與 TTL

網域指到機器靠 DNS 記錄:A 記錄填 IPv4 位址,AAAA 記錄填 IPv6 位址,兩種都有就兩筆都設。www 常見的做法是用 CNAME 指回主網域,再由網頁伺服器把其中一個轉向另一個。

TTL 是這筆記錄可以被快取多久。RFC 1035 的定義是一個以秒為單位的欄位,說明記錄在重新向來源查詢之前可以被快取多長時間,填 0 表示不要快取。所以你改了記錄,全世界不會同時看到新值:要搬機器就提前把 TTL 調短,例如 300 秒,搬完再調回去。可選的值以你的 DNS 供應商官網為準。

流程圖:網站資料夾經由 SSH 送上 VPS,再由 DNS 記錄、反向代理與憑證三件事撐起來,讀者才會看到有鎖頭的網域
上面一排是檔案怎麼上去,中間三格是上線必須同時成立的三件事,最下面是讀者看到的結果。 · 圖片:Mokaair (© Mokaair)
閱讀完整文字說明

上排由左至右三格,說明檔案怎麼上去:你電腦上的網站資料夾,裡面是 index.html 或一個要先啟動的專案;用 rsync 或 git clone 走 SSH 連接埠 22 送上 VPS;檔案落在伺服器上的目錄,只有你的金鑰進得去。中排三格是上線必須同時成立的三件事。第一格 DNS,說明機器在哪裡:A 記錄填 IPv4 位址,AAAA 記錄填 IPv6 位址,TTL 決定舊答案還會被快取多久,沒生效前連到的還是舊位置。第二格反向代理,說明誰來回答:Caddy 或 Nginx 收下連接埠 80 與 443,靜態檔直接送出,應用程式轉給 systemd 管的服務,應用程式本身只監聽本機。第三格憑證,瀏覽器才信任:Let's Encrypt 預設效期 90 天,建議每 60 天自動續發一次,驗證要從連接埠 80 進得來。三格往下匯到最後一格:讀者打開你的網域,看到鎖頭;防火牆 ufw 只放行 22、80、443,其餘一律擋掉。

把每一步交給 AI 代理:提示詞怎麼寫

每一步都可以請 AI 代理代勞,但要給它三樣東西:機器現在的狀態、你要的結果、不准做的事。最有用的一句是「先列出你打算執行的指令和理由,等我確認再執行」;刪除檔案、覆寫設定檔、改防火牆規則,自己讀過再放行。

提示詞範本:每一步怎麼交給 AI 代理 · text
【選機器】我要把一個(靜態網站/Node.js 專案/Python 專案)放到 VPS,讀者主要在台灣。
請列出最低的記憶體與磁碟需求並說明你怎麼估的,作業系統假設是 Ubuntu LTS。
不要推薦主機商,也不要寫價格,我會自己去各家官網查。

【加固】這台機器剛開好,系統是 Ubuntu LTS。請給我一份步驟清單:
建立一般使用者、設定金鑰登入、關閉密碼登入、開啟 ufw、打開自動安全更新。
每一步先寫出指令和它會改到哪個檔案,等我說「執行」再動手。

【送檔案】我的網站在本機的 ~/site,伺服器上要放在 /var/www/site。
請給我 rsync 指令,第一次不要加 --delete,並說明怎麼確認傳完是對的。

【開 HTTPS】我要用 Caddy 提供 /var/www/site,網域是 example.com。
請寫出 Caddyfile 的內容,並列出重新載入設定與查看記錄的指令。

【跑應用程式】我的 Node.js 專案在 /home/deploy/app,用 node server.js 啟動、監聽 3000。
請寫一個 systemd 服務單元,讓它開機自動啟動、掛掉自動重啟,並確認它只監聽本機。

【指網域】我的網域要指到這台機器,位址是 203.0.113.10。
請說明我該新增哪幾筆 DNS 記錄、TTL 先設多少,以及用什麼指令確認已經生效。

【驗收】請列出一份上線檢查清單:HTTPS、憑證自動續發、防火牆、備份、記錄,
每一項寫出我該執行哪一個指令、看到什麼才算通過。

上線後的檢查清單與三個常見卡關

網址打得開只是第一關。下面這張表把流程折成八步,每一步都寫了怎麼確認做對;憑證續發與備份還原出問題時,都是安靜地壞掉。

上線流程與驗收方式,查證於 2026 年 9 月。
步驟要做什麼怎麼確認做對了
選機器地區、記憶體、Ubuntu LTS、快照建一次快照,記下還原從哪裡按
鎖好門金鑰登入、一般使用者、關密碼登入、開 ufw另開視窗能登入;ufw status verbose 只列 22、80、443
自動更新裝 unattended-upgradesunattended-upgrade --dry-run 沒錯誤
送檔案rsync 同步,或在伺服器 git clone檔案數量與首頁檔名都對
開 HTTPSCaddy,或 Nginx 加 certbot網址列出現鎖頭,HTTP 會自動轉址
跑應用程式寫 systemd 單元,前面反向代理status 是 active;重開機後還在
指網域設 A 與 AAAA 記錄,先調短 TTL用 dig 查到的就是這台機器
持續顧著排程快照、留意續發、看記錄做一次還原演練;renew --dry-run 通過

  • 生活分享

    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 的官方文件。

最新旅遊情報攻略

資料來源

生活分享