IoTLabs

Nghiên cứu, Sáng tạo và Thử nghiệm

Series: Lập trình Raspberry Pi – Bài 17: Chạy FastAPI như service (systemd) + reverse proxy Nginx + HTTPS nội bộ

Series: Lập trình Raspberry Pi & Ứng dụng thực tế Phần 3 — Python “build app thật” Bài 17: Chạy FastAPI như service (systemd) + reverse proxy Nginx + HTTPS nội bộ

1) Mục tiêu bài học

Sau bài này bạn sẽ:

  • Chạy FastAPI (uvicorn) như systemd service: auto-start, restart, logs.
  • Dùng Nginx reverse proxy để truy cập bằng port 80 (hoặc 443).
  • (Tuỳ chọn) Bật HTTPS nội bộ bằng self-signed cert (dùng trong LAN).

2) Chuẩn bị

  • Project đã chạy được uvicorn src.api:app (Bài 13/16)
  • Bạn có user chạy app (ví dụ developer)
  • Port dự kiến:
    • Uvicorn: 127.0.0.1:8000
    • Nginx public: 80 (và 443 nếu bật TLS)

Cài Nginx:

sudo apt update
sudo apt -y install nginx

3) Systemd service cho FastAPI

Tạo file:

sudo nano /etc/systemd/system/iotlabs-api.service

Dán cấu hình (đổi đường dẫn cho đúng user/thư mục của bạn):

[Unit]
Description=IoTLabs FastAPI (Pi Dashboard/API)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=developer
WorkingDirectory=/home/developer/apps/iotlabs-py-agent

# dùng uvicorn trong venv
ExecStart=/home/developer/apps/iotlabs-py-agent/.venv/bin/uvicorn src.api:app \
  --host 127.0.0.1 --port 8000

Restart=always
RestartSec=3

# log ra journald
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Enable + start:

sudo systemctl daemon-reload
sudo systemctl enable iotlabs-api
sudo systemctl start iotlabs-api
sudo systemctl status iotlabs-api --no-pager

Xem log:

journalctl -u iotlabs-api -n 80 --no-pager
journalctl -u iotlabs-api -f

4) Nginx reverse proxy (port 80 → 8000)

Tạo config site:

sudo nano /etc/nginx/sites-available/iotlabs-api

Dán:

server {
    listen 80;
    server_name _;

    location / {
        proxy_pass         http://127.0.0.1:8000;
        proxy_http_version 1.1;

        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable site:

sudo ln -s /etc/nginx/sites-available/iotlabs-api /etc/nginx/sites-enabled/iotlabs-api
sudo nginx -t
sudo systemctl restart nginx

Mở browser:

  • http://<IP_CUA_PI>/

5) (Tuỳ chọn) HTTPS nội bộ bằng self-signed cert

Tạo cert (1 năm):

sudo mkdir -p /etc/nginx/certs
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/nginx/certs/iotlabs.key \
  -out /etc/nginx/certs/iotlabs.crt \
  -subj "/CN=iotlabs-pi.local"

Sửa config Nginx:

sudo nano /etc/nginx/sites-available/iotlabs-api

Thay bằng:

server {
    listen 80;
    server_name _;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name _;

    ssl_certificate     /etc/nginx/certs/iotlabs.crt;
    ssl_certificate_key /etc/nginx/certs/iotlabs.key;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Test & restart:

sudo nginx -t
sudo systemctl restart nginx

Truy cập:

  • https://<IP_CUA_PI>/ hoặc https://iotlabs-pi.local/ (nếu mDNS ok)

Trình duyệt sẽ cảnh báo vì self-signed — bình thường trong LAN. Muốn “xịn” hơn: dùng CA nội bộ hoặc Let’s Encrypt (khi có domain public).

6) Firewall (UFW) gợi ý

Nếu bạn bật UFW:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status

7) Checklist debug nhanh

  • systemctl status iotlabs-api fail:
    • sai đường dẫn venv …/.venv/bin/uvicorn
    • sai WorkingDirectory
  • Nginx 502 Bad Gateway:
    • uvicorn chưa chạy hoặc bind sai host/port
    • check: curl -s http://127.0.0.1:8000/health
  • Port 80 không vào được:
    • UFW chưa mở
    • service nginx chưa restart / config lỗi (nginx -t)