一台 2015 年的 MacBook Pro,到 2026 年已經不是什麼理想的日常工作電腦。

但這不代表它沒有計算價值。

如果硬體仍然正常、有 SSD、有記憶體、有 Gigabit Ethernet,而且大部分工作本來就可以容器化,那它其實更適合脫離桌面作業系統,變成一台長期在線的 Linux Server。

一、改裝目標與最後架構

這次我的目標很單純:

把一台 MacBook Pro 2015 完全清除 macOS,安裝 Debian 13,只留下 SSH、Docker、Tailscale,最後關上螢幕,當成一台 24 小時運作的 Docker Server。

實際完成後,架構是:

MacBook Pro 2015
│
├─ Debian 13
├─ OpenSSH
├─ Docker Engine
├─ Docker Compose
├─ Tailscale
│
├─ 2TB internal SSD
│
└─ USB Gigabit Ethernet

日常管理則完全不碰 MacBook:

Windows / 其他電腦
        │
        ├─ LAN SSH
        │
        └─ Tailscale SSH
                │
                ▼
          Debian Server
                │
             Docker

這篇記錄整個實際安裝流程,包括幾個 2015 MacBook 特有的坑。

二、為什麼最後選 Debian,而不是 Ubuntu?

最初其實考慮的是 Ubuntu Server。

Ubuntu 的優點非常明顯:文件多、教學多、遇到問題容易查,而且 Docker 支援也很好。

但這台機器的目的不是當 Linux 工作站,而是:

開機 → SSH → Docker → 長時間不碰 OS

最後因此選 Debian 13。

Debian 在這個情境下的優勢不是「效能突然快很多」,而是系統層比較簡單。沒有 GUI,沒有不必要的桌面服務,也不需要安裝 GNOME、KDE、Xfce。

這台電腦的工作不是讓人操作,而是讓程式運作。對 Server 而言,這是一個重要差別。

三、硬體與安裝前準備

這次使用:

  • MacBook Pro 2015
  • Intel x86-64
  • 內建 SSD:2TB
  • 安裝媒體:32GB USB
  • 網路:USB → Gigabit Ethernet

原本的 SSD 已經升級到 2TB,因此磁碟容量對 Docker、資料庫、Crawler、Agent 等服務都相當充裕。

安裝前先完成所有 macOS 資料備份。

因為這次不是 Dual Boot,而是準備直接清掉整顆 SSD。

四、製作 Debian 安裝 USB

下載 Debian 13 amd64 netinst ISO,再使用 Rufus 把 ISO 寫入 32GB USB。

Rufus 的基本設定:

  • Boot selection:Debian ISO
  • Partition scheme:GPT
  • Target system:UEFI

寫入完成後,把 USB 插入 MacBook。關機,再按電源鍵後立刻長按:

Option ⌥

直到出現 Apple 的開機磁碟選擇畫面。選擇 EFI Boot,即可從 Debian USB 啟動。

五、開始安裝 Debian

Debian Installer 有文字與圖形版本。我直接選:

Graphical install

雖然最後不會安裝桌面 GUI,但安裝時使用 Graphical Installer 比較方便。

語言我選 English。Server 上使用英文環境的好處很實際:未來查 log、錯誤訊息與 Linux 文件時,不需要再做翻譯。

設定大致如下:

Language:English
Location:Taiwan
Keyboard:American English

六、MacBook 2015 的 Broadcom Wi-Fi firmware 問題

安裝器很快就跳出:

Some of your hardware needs non-free firmware files...
brcmfmac43602...

這是 MacBook 2015 內建的 Broadcom Wi-Fi。

但這台機器本來就準備作為 Server,因此我沒有打算依賴 Wi-Fi。機器上已經接了一張 USB Ethernet,所以 firmware 畫面直接選 No

接著 Debian 成功偵測出兩個網路介面:

enx........     USB Ethernet
wlp3s0          Broadcom Wi-Fi

選擇 enx........ 後,DHCP 成功拿到 IP。這也證明 USB Ethernet 可以直接使用,不需要額外驅動。

對 Server 而言,我反而認為這是更好的架構:

Router
  │
Ethernet
  │
USB Ethernet
  │
MacBook

比依賴十年前的 Broadcom Wi-Fi 可靠。

七、設定 Hostname、使用者與 root

Hostname 設為:

mbp-server

Domain name 留白。家用網路和 Tailscale 環境沒有必要硬設定 DNS domain。

之後 Linux shell 就會變成:

alan@mbp-server:~$

Debian Installer 接著會要求設定 root password。我選擇兩格全部留白。

這樣 root 不直接登入,而是建立一般使用者後用 sudo 取得管理權限。

接著建立:

Full name:Alan
Username:alan
Password:自行設定

之後執行 sudo apt update,就會使用 alan 的密碼取得權限。

八、清除 macOS:整顆 SSD 給 Debian

磁碟分割選:

Guided - use entire disk and set up LVM

不要選:

largest continuous free space

因為那通常意味著保留既有 macOS partition。

接著 Installer 顯示兩顆磁碟:

/dev/nvme0n1
2.0 TB internal SSD

/dev/sda
31 GB USB

這裡一定要確認。我選的是 /dev/nvme0n1,也就是 2TB 內建 SSD。31GB 那顆是 Debian 安裝 USB,不能選錯。

接著選:

All files in one partition

這對 Docker Server 非常合理。如果過早把 /home/var/srv 切成固定大小,未來很容易出現 /var/lib/docker 滿了,但其他 partition 還有大量空間的情況。

因此先讓整顆 SSD 共用空間。LVM 容量直接選 2.0 TB,最後確認:

Write changes to disk → Yes

這一步之後,原本的 macOS 就正式消失了。

九、Mirror 與最重要的套件選擇

Debian Mirror 設定:

Mirror country:Taiwan
Mirror:deb.debian.org
HTTP proxy:留白
Package usage survey:No

Debian Installer 接著會問要安裝哪些軟體。預設可能包含 Debian desktop environment、GNOME、Xfce、KDE 等選項。

桌面環境全部取消,最後只留下:

[X] SSH server
[X] standard system utilities

這一步決定了這台機器之後不會有桌面。沒有 Dock、桌布、Finder、瀏覽器、視窗或桌面環境。

開機後只會看到:

Debian GNU/Linux 13 mbp-server tty1
mbp-server login:

這就是我要的。

十、第一次開機與 Retina TTY

安裝完成後拔掉 Debian USB,重新開機並登入:

login: alan
password: ********

成功後會看到:

alan@mbp-server:~$

到這裡,MacBook 已經正式變成 Linux Server。

不過,一開機馬上會發現 MacBook Retina 配 Debian TTY,字小得離譜。可以執行:

sudo dpkg-reconfigure console-setup

設定例如:

Encoding:UTF-8
Font:Terminus
Font size:16x32

Server 日後主要透過 SSH 使用,所以這只是讓本機 emergency console 比較容易閱讀。

十一、確認 Ethernet,從 Windows SSH 登入

先確認網路介面:

ip -br a

可以看到類似:

lo               UNKNOWN   127.0.0.1/8
enx........       UP        192.168.1.xxx/24
wlp3s0            DOWN

代表 USB Ethernet 正常,Wi-Fi 未使用。

測試外網與 DNS:

ping -c 4 1.1.1.1
ping -c 4 deb.debian.org

兩個都成功後,Server 網路完成。

同一個區網的 Windows 即使使用 Wi-Fi,也可以連到接 Ethernet 的 MacBook,只要兩台都在相同 LAN。

在 PowerShell 執行:

ssh alan@192.168.1.xxx

第一次會看到:

The authenticity of host ... can't be established.

確認連線對象與指紋無誤後輸入 yes,再輸入 Debian 的 alan 密碼。成功後就會看到 alan@mbp-server:~$

從這個時間點開始,我幾乎就不需要再碰 MacBook 的鍵盤了。

接著先更新 Debian:

sudo apt update
sudo apt upgrade -y

本次系統顯示:

Upgrading: 0
Installing: 0
Removing: 0
Not Upgrading: 0

然後重新開機:

sudo reboot

SSH 會自然斷線。等機器重新啟動後再連回去即可。

十二、安裝與測試 Docker Engine

這次沒有使用 Debian 自帶的 docker.io,而是使用 Docker 官方 repository。

先安裝必要套件:

sudo apt install -y ca-certificates curl

建立 keyring:

sudo install -m 0755 -d /etc/apt/keyrings

加入 Docker GPG key:

sudo curl -fsSL https://download.docker.com/linux/debian/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

建立 repository:

sudo tee /etc/apt/sources.list.d/docker.sources > /dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: trixie
Components: stable
Architectures: amd64
Signed-By: /etc/apt/keyrings/docker.asc
EOF

更新並安裝 Docker:

sudo apt update
sudo apt install -y \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin

執行測試:

sudo docker run hello-world

看到以下訊息,表示 Docker daemon、Docker Hub 與 container runtime 都正常:

Hello from Docker!
This message shows that your installation appears to be working correctly.

為了讓一般帳號直接使用 Docker,可以把 alan 加入 docker group:

sudo usermod -aG docker alan

接著執行 exit,重新 SSH 登入,再測試:

docker ps
docker compose version

本次環境顯示:

Docker Compose version v5.5.0

代表 Docker Compose plugin 也正常。

十三、安裝 Tailscale,從外面 SSH 回家

LAN SSH 解決了家裡管理。但我要的是:人不在家,也能安全連回這台 Server。

這裡使用 Tailscale。安裝:

curl -fsSL https://tailscale.com/install.sh | sh

啟動:

sudo tailscale up

Terminal 會產生一個登入網址。用瀏覽器登入並授權這台 mbp-server

完成後執行:

tailscale ip -4

會得到:

100.x.x.x

這是這台 MBP 的 Tailscale IP。

另一台 Windows 也加入同一個 Tailnet 後,可以:

ssh alan@100.x.x.x

這裡使用的仍然是 Debian alan 的密碼,不是 Tailscale 密碼。

因為 Tailscale 負責的是網路連線,真正執行 SSH authentication 的仍然是 Debian OpenSSH。因此:

ssh alan@192.168.1.xxx
ssh alan@100.x.x.x

其實都是登入同一台 mbp-server、同一個 alan、同一個密碼、同一把 SSH Host Key,只是走不同路徑。

不要把 SSH 密碼接在指令後面

一個很容易犯的錯是:

ssh alan@IP我的密碼

這是錯的。正確一定是:

ssh alan@IP

看到 alan@IP's password: 再輸入密碼。

Linux/SSH 在輸入密碼時不會顯示 * 或圓點,畫面看起來完全沒有反應,這是正常行為。

十四、讓 MacBook 闔蓋後繼續運作

Server 最大的問題來了:MacBook 是筆電,正常情況下關上 lid 就會 suspend。

但我要的是:

  • 螢幕關掉
  • MacBook 闔起來
  • Docker 照跑
  • SSH 照連

編輯:

sudo nano /etc/systemd/logind.conf

設定:

HandleLidSwitch=ignore
HandleLidSwitchExternalPower=ignore

注意前面不能有 #,因為 #HandleLidSwitch=ignore 只是註解,並沒有真正生效。

儲存後:

sudo systemctl restart systemd-logind

確認:

grep -E '^HandleLidSwitch|^HandleLidSwitchExternalPower' \
  /etc/systemd/logind.conf

應該看到:

HandleLidSwitch=ignore
HandleLidSwitchExternalPower=ignore

再做第二層保險,把 sleep/suspend 完全關掉:

sudo systemctl mask \
  sleep.target \
  suspend.target \
  hibernate.target \
  hybrid-sleep.target

系統會建立:

sleep.target → /dev/null
suspend.target → /dev/null
hibernate.target → /dev/null
hybrid-sleep.target → /dev/null

代表這些 target 已被 mask。

十五、確認自動啟動並進行闔蓋測試

確認 Docker 與 Tailscale 開機自動啟動:

systemctl is-enabled docker
systemctl is-enabled tailscaled

兩個都應該回傳:

enabled

再確認 Docker status:

systemctl status docker --no-pager

正常應該是:

Active: active (running)

本次 Docker daemon 空載時記憶體大約只有數十 MB。這也是為什麼這種舊機器很適合做 headless Linux Server。

設定好之後,我直接把 MBP 螢幕蓋上。等了一兩分鐘,另一台 Windows 先測 LAN:

ssh alan@192.168.1.xxx

成功。再測 Tailscale:

ssh alan@100.x.x.x

也成功。

這才算真正證明:

MacBook Lid Closed
        │
        ▼
Debian 仍運作
Docker 仍運作
Ethernet 仍運作
SSH 仍運作
Tailscale 仍運作

到這一步,這台 MacBook 才正式完成 Server 化。

十六、停電與服務恢復

MacBook 做家庭 Server 有一個意外的優點:它自己就有電池。

一般 mini PC
市電中斷 → 直接斷電

MacBook
市電中斷 → 自動切換內建電池 → Server 繼續運作

也就是自帶一個小型 UPS。如果只是短暫停電,甚至可能完全不會中斷服務。

如果停電時間長到電池耗盡,Debian 關機、Docker 停止。恢復供電之後,這台老 MacBook 未必會自動開機。

我的情況並不要求完全 unattended,所以最壞情況只需要有人:

掀開 MacBook → 按電源鍵

Debian 開機後,Docker、Tailscale、SSH 都會自動恢復。

如果每個 Docker service 又設定:

restart: unless-stopped

application container 也可以自行恢復。

十七、這台 Server 適合做什麼?

完成 Server 化後,它的用途其實比繼續當一台十年前的 macOS 筆電廣很多。

特別適合:

  • Docker services
  • Crawler、Playwright、Python worker
  • Cron、Webhook、Scheduler
  • LINE Bot、Telegram Bot
  • API Server、Laravel、FastAPI、Node.js
  • PostgreSQL、Redis、Nginx
  • Cloudflare Tunnel、n8n、Gitea
  • Uptime Kuma、Syncthing、Samba
  • AI Agent orchestration、LLM API worker、CI/CD

不適合:

  • 大型 Local LLM
  • Stable Diffusion
  • ComfyUI 大型 workload
  • Video generation
  • CUDA workload

原因很簡單:它沒有現代 NVIDIA GPU。

因此它最合理的角色不是 AI GPU machine,而是 Always-on Infrastructure Node

我現在把它看成:

MacBook Pro 2015
        │
        ▼
Debian Control / Service Node
        │
        ├─ Docker
        ├─ Database
        ├─ Crawler
        ├─ API
        ├─ Agent
        ├─ Queue
        ├─ Scheduler
        └─ Monitoring

GPU 工作仍然交給另外一台有 RTX GPU 的 Windows workstation。

這台 MBP 負責 Always-on、Low-power、Networking、Scheduling、Orchestration、Storage 與 Services。兩者其實是完全不同的工作。

十八、第一批準備搬進來的服務:Crawler

我目前沒有打算急著把 production Web Server 從雲端搬回家。

因為原本的 Lightsail 每個月成本只有大約 USD 24。為了省這筆費用,把已經穩定運作的 production system 從雲端移回一台 2015 年筆電,其實不是很好的交易。

比較合理的是:

Lightsail
→ Production
→ 公開 Web
→ Critical DB

MBP
→ Crawlers
→ Workers
→ AI agents
→ Batch jobs
→ Internal services

尤其爬蟲非常適合第一批搬回來。Crawler 通常:

  • 不需要外部 inbound port
  • 不要求 99.99% uptime
  • CPU/RAM/bandwidth 有實際需求
  • 可以容忍短暫中斷

這正好適合家庭 Server。

未來可以建立:

/srv/docker/
├── crawlers/
├── agents/
├── monitoring/
├── postgres/
├── redis/
└── tools/

/srv/data/

把 application 與 persistent data 分開管理。

十九、最後的結果

原本它是一台:

2015 MacBook Pro
老舊 macOS
日常價值持續下降

現在變成:

2015 MacBook Pro
      │
      ▼
Debian 13
      │
      ├── OpenSSH
      ├── Docker
      ├── Docker Compose
      ├── Tailscale
      ├── 2TB SSD
      └── Gigabit Ethernet

平常螢幕完全關起來。沒有 GUI,沒有滑鼠,沒有桌面。我甚至不需要坐在它前面。

在家:

ssh alan@192.168.1.xxx

在外:

ssh alan@100.x.x.x

然後直接開始工作。

這可能才是很多十年前 Intel Mac 最合理的生命延長方式。

不是努力讓它繼續像一台 2026 年的筆電。

而是停止要求它做一台現代筆電,讓它改做一件舊 CPU 到現在仍然非常擅長的事情:

安靜地、持續地執行程式。