Loại bỏ Cloud Key: Tự host UniFi Network Application trên Docker

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

Cái giá phải trả của việc quản lý tập trung

Thiết bị Ubiquiti UniFi là lựa chọn hàng đầu cho HomeLab, nhưng nó có một nhược điểm. Không giống như các router phổ thông, bạn không thể chỉ đăng nhập vào địa chỉ IP của Access Point để thay đổi SSID. Những thiết bị này cần một “bộ não” trung tâm: UniFi Network Application. Trong nhiều năm, Ubiquiti đã hướng người dùng sử dụng Cloud Key, một thiết bị phần cứng độc quyền giá 200 USD, hoặc cổng thông tin đám mây của họ.

Mua một chiếc Cloud Key sẽ tiêu tốn thêm 13W điện năng cho tủ rack của bạn và tạo ra một điểm lỗi duy nhất (single point of failure). Các thiết bị này vốn nổi tiếng with lỗi phồng pin nội bộ và hỏng thẻ microSD. Việc dựa vào đám mây cũng không khá hơn là bao. Nó gây ra độ trễ và chuyển giao sơ đồ mạng riêng tư của bạn cho một máy chủ bên thứ ba. Nếu mất internet hoặc thiếu một giải pháp truy cập từ xa đáng tin cậy, khả năng quản lý phần cứng cục bộ của bạn thường cũng biến mất theo.

Tách rời phần mềm khỏi phần cứng sẽ giải quyết vấn đề này. Bằng cách đưa UniFi controller vào một Docker container, bạn giành lại quyền kiểm soát hạ tầng của mình. Bạn tiết kiệm được tiền, giảm bớt sự bừa bãi và giữ dữ liệu ở đúng nơi: trên ổ đĩa của chính mình.

So sánh các phương thức host

Việc chọn phương thức host phù hợp tùy thuộc vào khả năng bảo trì và ngân sách của bạn. Trong một HomeLab chuyên nghiệp, việc giám sát hệ thống và duy trì hiệu quả là trên hết. Docker luôn giành chiến thắng vì nó cân bằng giữa khả năng kiểm soát và sự dễ dùng.

Phương thức Chi phí ban đầu Bảo trì Quyền riêng tư dữ liệu
Cloud Key Gen2 Plus $199+ Thấp Cục bộ
Tài khoản Cloud UI.com Miễn phí / Trả phí Không có Bên ngoài
App Windows/Mac Miễn phí Cao (Máy tính phải luôn bật) Cục bộ
Docker Container Miễn phí Tự động hóa Hoàn toàn cục bộ

Tại sao Docker là lựa chọn vượt trội

Docker không chỉ là về việc tiết kiệm 200 USD. Nó thay đổi cách bạn quản lý vòng đời mạng của mình. Nếu bạn quyết định nâng cấp từ một chiếc Raspberry Pi lên một chiếc NUC cấu hình cao, bạn không cần phải cấu hình lại mạng. Bạn chỉ cần di chuyển volume dữ liệu và pull image mới.

Kiểm soát phiên bản là cứu cánh. Ubiquiti thỉnh thoảng phát hành các bản cập nhật gây lỗi khi nhận diện (adoption) các AP đời cũ. Với Docker, bạn có thể rollback về phiên bản image trước đó chỉ trong vài giây. Việc backup cũng đơn giản không kém. Vì tất cả cấu hình nằm trong một thư mục được map (ánh xạ), chỉ cần một lệnh tar hoặc một script tự động là có thể sao lưu toàn bộ trạng thái mạng của bạn.

Có một vài trở ngại nhỏ. Bạn sẽ cần quản lý IP, port mapping và thiết lập cơ sở dữ liệu. Các phiên bản UniFi hiện đại (7.5+) không còn đi kèm cơ sở dữ liệu tích hợp, yêu cầu một instance MongoDB riêng biệt để hoạt động.

Stack hiện đại: UniFi + MongoDB 7.0

Kiến trúc ổn định nhất là sử dụng docker-compose để liên kết ứng dụng UniFi với MongoDB. Tôi khuyên dùng các image của LinuxServer.io. Chúng được cập nhật thường xuyên và xử lý quyền hạn tệp tin (file permissions) mượt mà hơn nhiều so với các bản build chính thức từ cộng đồng.

Hướng dẫn triển khai

1. Tổ chức thư mục

Bắt đầu bằng cách tạo một cấu trúc thư mục sạch sẽ. Điều này giúp ngăn các tệp cấu hình nằm rải rác trên hệ thống host của bạn.

mkdir -p ~/unifi-stack/config
mkdir -p ~/unifi-stack/db
cd ~/unifi-stack

2. Cấu hình Docker Compose

Tạo một tệp docker-compose.yml. Script này định nghĩa môi trường và mở các port cụ thể cần thiết cho việc khám phá thiết bị L2 và giao diện quản lý.

version: "3.8"
services:
  unifi-db:
    image: mongo:7.0
    container_name: unifi-db
    volumes:
      - ./db:/data/db
      - ./init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
    restart: unless-stopped

  unifi-network-application:
    image: lscr.io/linuxserver/unifi-network-application:latest
    container_name: unifi-network-application
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/New_York
      - MONGO_USER=unifi
      - MONGO_PASS=unifi-password
      - MONGO_HOST=unifi-db
      - MONGO_PORT=27017
      - MONGO_DBNAME=unifi
      - MEM_LIMIT=1024
    volumes:
      - ./config:/config
    ports:
      - 8443:8443 # Giao diện Web
      - 3478:3478/udp # STUN
      - 10001:10001/udp # Khám phá thiết bị
      - 8080:8080 # Thông báo thiết bị
    restart: unless-stopped
    depends_on:
      - unifi-db

3. Tự động hóa thiết lập cơ sở dữ liệu

UniFi yêu cầu một người dùng cơ sở dữ liệu cụ thể. Tạo tệp init-mongo.js trong thư mục của bạn để xử lý việc này tự động trong lần khởi động đầu tiên:

db.getSiblingDB('unifi').createUser({
  user: 'unifi',
  pwd: 'unifi-password',
  roles: [{ role: 'dbOwner', db: 'unifi' }, { role: 'dbOwner', db: 'unifi_stat' }]
});

4. Triển khai Stack

Khởi chạy các container ở chế độ chạy ngầm (detached mode):

docker-compose up -d

Hãy kiên nhẫn. Các ứng dụng dựa trên Java cần thời gian để khởi động. Thường mất khoảng 120 giây để web server có thể phản hồi. Bạn có thể theo dõi tiến trình bằng cách chạy lệnh docker logs -f unifi-network-application.

Nhận diện thiết bị (Adopting)

Truy cập vào https://<your-ip>:8443. Bạn sẽ thấy cảnh báo SSL; điều này là bình thường đối với các chứng chỉ tự ký (self-hosted). Nếu các AP không xuất hiện ngay lập tức, chúng có thể cần được kích hoạt thủ công. SSH vào AP của bạn (thông tin đăng nhập mặc định là ubnt/ubnt) và trỏ nó về controller mới của bạn:

set-inform http://<your-server-ip>:8080/inform

Mẹo bảo trì cuối cùng

Quản lý bộ nhớ là cực kỳ quan trọng. Đối với một gia đình thông thường có ba AP, 1GB RAM là mức lý tưởng. Nếu bạn thấy giao diện bị lag, hãy nâng MEM_LIMIT lên 2048. Ngoài ra, đừng quên chọn tùy chọn “Switch to Local User” trong trình hướng dẫn thiết lập. Điều này giúp bỏ qua yêu cầu tài khoản UI.com, đảm bảo mạng của bạn vẫn có thể truy cập được ngay cả khi mất kết nối internet.

Share: