Mac mini 2014 Home Server: Tham chiếu Setup
Mac mini Late 2014 đã được chuyển thành home server chạy Xubuntu. Trạng thái hiện tại: boot từ SSD Kingmax 120 GB qua USB, HDD Apple 1 TB bên trong đã format ext4 và mount tại /data, SSH và Tailscale hoạt động ổn định sau reboot headless. Docker chưa cài.
Đây là snapshot lịch sử tại 2026-09-09T17:00:00+07:00. Các cụm “hiện tại” và checklist “chưa làm” bên dưới chỉ mô tả state ở thời điểm đó; những baseline sau đã chuyển host sang Ubuntu, cài Docker và bổ sung hardening/monitoring.
Bản chất
Đây là note tham chiếu trạng thái thực tế của hệ thống — không phải tutorial từ đầu. Mục đích là ghi lại những gì đã làm, lý do quyết định từng bước, và trạng thái hiện tại để tiếp tục setup.
Kiến trúc hiện tại:
Mac mini Late 2014 — RAM 8 GB
│
├── Kingmax SSD 120 GB — USB
│ ├── ext4 / (Xubuntu + system)
│ └── vfat /boot/efi (UEFI boot entry)
│
└── Apple HDD 1 TB — SATA nội bộ
└── ext4 /data (dữ liệu, Docker volumes)Mục tiêu storage tiếp theo:
SSD 120 GB → Xubuntu, Docker Engine, application binaries
HDD 1 TB → /data (media, downloads, backups, Docker persistent data)Vì sao lựa chọn
Tại sao boot từ SSD ngoài (USB) thay vì dùng HDD nội bộ?
Mac mini 2014 dùng HDD SATA 1 TB — I/O chậm cho system workload. SSD dù qua USB vẫn cải thiện hiệu năng desktop đáng kể và cho phép dùng toàn bộ HDD 1 TB làm storage dữ liệu mà không phải partition HDD theo kiểu phức tạp.
Tại sao giữ ext4 cho HDD thay vì ZFS hay btrfs?
Mục tiêu đơn giản: một partition ext4 duy nhất chiếm toàn bộ 1 TB, mount tại /data. ext4 được Ubuntu hỗ trợ trực tiếp và đủ cho setup một data disk không cần RAID hay snapshot ở giai đoạn này. ZFS hoặc btrfs sẽ có giá trị hơn khi có nhiều disk và cần RAID/snapshot.
Tại sao dùng UUID trong /etc/fstab thay vì /dev/sda1?
Thứ tự nhận disk có thể thay đổi giữa các lần boot — đặc biệt khi có cả USB và SATA. Trong setup này, HDD từng xuất hiện là /dev/sda1 sau đó chuyển thành /dev/sdb1 sau reboot. UUID thuộc filesystem, không thay đổi dù device name đổi. fstab với UUID đảm bảo /data luôn mount đúng HDD bất kể thứ tự boot.
Đánh đổi:
- SSD qua USB có overhead hơn SSD nội bộ, nhưng với workload server thông thường (SSH, Docker, file serving) không đáng kể.
- Chỉ một disk lưu dữ liệu — không có redundancy. Nếu HDD hỏng, mất dữ liệu. Backup strategy là phần cần làm tiếp theo.
Cơ chế hoạt động
Boot flow Mac mini:
Power on
│ Giữ Option/Alt
▼
Apple Startup Manager
│ Scan USB và SATA cho EFI boot entries
▼
Chọn "EFI Boot" (từ Kingmax SSD)
│
▼
GRUB load từ /boot/efi trên SSD
│
▼
Xubuntu boot từ ext4 / trên SSD
│
├── tailscaled.service start
├── ssh.service start
└── /data auto-mount từ fstab (UUID → HDD 1 TB)fstab UUID mount mechanism:
Kernel boot
│ đọc /etc/fstab
│ thấy entry: UUID=<xyz> /data ext4 defaults,nofail 0 2
▼
Kernel gọi udev để tìm device có filesystem UUID=<xyz>
│ scan tất cả block devices
▼
Tìm thấy UUID trên /dev/sdb1 (hoặc /dev/sda1 tuỳ thứ tự boot)
│
▼
Mount /dev/sdb1 tại /datanofail trong fstab options đảm bảo boot không bị block nếu HDD không được nhận — server vẫn lên và SSH được, chỉ là /data không có.
Hướng dẫn từng bước
Thiết lập đã hoàn thành — SSH và Tailscale
Chi tiết trong note headless-home-server-ssh-tailscale. Trạng thái hiện tại: SSH và Tailscale đã hoạt động sau reboot.
Thiết lập đã hoàn thành — Format và mount HDD
Xác định disk trước mọi thao tác destructive:
lsblk -o NAME,SIZE,MODEL,TRAN,FSTYPE,LABEL,MOUNTPOINTS
# Phân biệt rõ SSD Kingmax (USB, 120 GB) và HDD Apple (SATA, ~1 TB)
# Không dựa chỉ vào tên /dev/sda hay /dev/sdbCác lệnh wipefs, parted và mkfs.ext4 bên dưới phá hủy partition/filesystem trên disk đích. Phải xác minh disk bằng model, size và transport; không copy nguyên /dev/sda sang máy khác.
Xóa partition table cũ của HDD (macOS APFS layout):
sudo wipefs -a /dev/sda
# Thay /dev/sda bằng device name thực tế của HDD Apple
# ⚠️ DESTRUCTIVE — chỉ chạy khi chắc chắn đúng deviceTạo GPT và partition mới:
sudo parted /dev/sda --script mklabel gpt
# mklabel gpt → tạo GPT partition table
# --script → non-interactive, không hỏi confirm
sudo parted /dev/sda --script mkpart primary ext4 0% 100%
# mkpart primary → tạo primary partition
# 0% 100% → chiếm toàn bộ dung lượng diskFormat ext4:
sudo mkfs.ext4 -L data /dev/sda1
# -L data → đặt label "data" cho filesystem
# Label giúp nhận diện thêm ngoài UUIDTạo mount point và mount thử:
sudo mkdir -p /data
sudo mount /dev/sda1 /data
# Kiểm tra trước khi cấu hình fstab
findmnt /data
df -h /data
# Kỳ vọng: ~870 GB available (1 TB - filesystem overhead)Cấu hình auto-mount trong fstab:
# Lấy UUID của partition data
sudo blkid /dev/sda1
# hoặc:
lsblk -f | grep sda1sudo nano /etc/fstabThêm dòng (dùng UUID thực tế):
UUID=<UUID-cua-partition-data> /data ext4 defaults,nofail 0 2Giải thích các field:
UUID=... → identifier của filesystem
/data → mount point
ext4 → filesystem type
defaults → standard mount options (rw, relatime, errors=remount-ro...)
nofail → boot không fail nếu device không tìm thấy
0 → dump (0 = không backup bằng dump)
2 → fsck order (2 = check sau root filesystem)sudo systemctl daemon-reload
# Reload systemd để nhận fstab changes
sudo mount -a
# -a → mount tất cả entry trong fstab chưa được mount
# Nếu có lỗi, sửa trước khi reboot
findmnt /data
# Phải thấy /data đang mountCấp quyền write cho user:
sudo chown <user>:<user> /data
# Cho phép user thông thường write vào /data mà không cần sudoTest:
touch /data/test.txt && rm /data/test.txt
# Không có lỗi = quyền cơ bản OKXác minh auto-mount sau reboot
sudo rebootSSH lại:
ssh <user>@<server-hostname>findmnt /data
df -h /data
# Phải thấy /data mount với HDD Apple
# Device name có thể đổi (sda1 → sdb1) nhưng mount vẫn đúng nhờ UUIDBước tiếp theo ở thời điểm snapshot — Docker Engine
Docker chưa được cài khi note này được ghi. Setup thực tế ở baseline sau dùng repository chính thức của Docker cho Ubuntu và đã verify docker.service, Compose và hello-world. Vì vậy không giữ planned curl | sh trong snapshot này như procedure hiện hành; khi cần cài lại, dùng installation guide chính thức và note baseline mới hơn.
Bẫy lỗi và Những lần thử thất bại
Bẫy 1 — mount -a báo “mount point does not exist”
Lần đầu thêm /data vào fstab và chạy mount -a, gặp lỗi mount: /data: mount point does not exist. Nguyên nhân: chưa tạo thư mục /data. fstab không tự tạo mount point directory — phải mkdir -p /data trước.
Bẫy 2 — Device name thay đổi sau reboot
HDD Apple xuất hiện là /dev/sda1 khi setup, sau reboot chuyển thành /dev/sdb1 (vì Kingmax SSD USB được nhận trước). Nếu fstab dùng /dev/sda1, /data sẽ mount vào Kingmax SSD thay vì HDD — hoặc fail hoàn toàn. UUID giải quyết vấn đề này.
Bẫy 3 — Kết luận hardware hỏng khi wipefs thành công nhưng lsblk vẫn thấy partition
Sau wipefs -a, chạy lsblk ngay lập tức đôi khi vẫn thấy partition cũ vì kernel cache chưa refresh. Chạy sudo partprobe /dev/sda hoặc reboot để kernel re-read partition table.
Bẫy 4 — chmod 777 /data vì “tiện”
Mở quyền 777 cho /data nghĩa là mọi process, mọi user trên máy đều có thể đọc/ghi/xoá. Khi Docker container chạy dưới UID khác, có thể overwrite data không có ý định. Nên dùng chown với user cụ thể và quản lý permission theo service.
Bẫy 5 — Cài nhiều service Docker cùng lúc trước khi verify từng bước
Cài Portainer, Jellyfin, qBittorrent, Nextcloud cùng lúc mà không verify từng service sau reboot — khi có sự cố không biết service nào gây ra. Thứ tự đúng: cài Docker → test container → verify sau reboot → cài service đầu tiên → verify → tiếp tục.
Kiểm tra và Xác minh
Checklist trạng thái hiện tại:
# Boot và SSH
systemctl is-enabled ssh tailscaled
systemctl is-active ssh tailscaled
# Kỳ vọng: enabled/enabled, active/active
# Storage
findmnt /data
df -h /data
# Kỳ vọng: /data mount, ~870 GB available
# Headless verification
sudo reboot
# SSH lại và chạy lại các lệnh trênChecklist những gì chưa làm:
[ ] Docker Engine
[ ] Docker Compose
[ ] Service self-host đầu tiên
[ ] Backup strategy cho /data
[ ] Wi-Fi BCM4360 (xem note bcm4360-wifi-ubuntu)
[ ] SSH hardening (PasswordAuthentication no)
[ ] UID/GID management cho Docker volumesNguồn tham khảo
- fstab man page:
man fstab
(giải thích đầy đủ các field và mount options) - systemd fstab integration
(giải thíchnofail,x-systemd.automountvà các option nâng cao) - Docker Engine installation — Linux
(script chính thức, tránh dùngdocker.iotừ APT vì thường là version cũ) - parted documentation
(reference cho GPT partitioning và mkpart syntax) - Các note liên quan trong cùng project:
headless-home-server-ssh-tailscale— SSH và Tailscale setup chi tiếtbcm4360-wifi-ubuntu— Wi-Fi driver cho Mac minixubuntu-external-ssd-mac-mini— Cài Xubuntu lên SSD ngoài