Hướng dẫn setup supabase storage upload an toàn cho web Next.js và ứng dụng nội bộ
· Tác giả: Trường — Founder Webchốt
Liên quan: Cần website bán hàng tải nhanh? Liên hệ Webchốt — thiết kế web bán hàng.
Bạn vừa chốt stack Next.js + Supabase cho cửa hàng online nhỏ hoặc SaaS nội bộ, nhưng vẫn lấn cấn chỗ lưu ảnh sản phẩm và file hoá đơn: để public thì sợ lộ, để private thì sợ làm chậm tải trang? Hay team chỉ có một developer part-time và cần checklist ngắn để không phải sửa RLS lúc nửa đêm? Bài này là hướng dẫn setup supabase storage upload theo hướng thực chiến — từ tạo bucket, policy RLS, signed URL, tới vài quy ước đặt tên file giúp bạn scale mà không tự bắn vào chân. Mình viết dựa trên các dự án Webchốt đã triển khai cho SME ở TP.HCM: ưu tiên bảo mật vượt trội, chi phí bandwidth minh bạch, và trải nghiệm tải ảnh mượt trên mobile.
Ước lượng egress và kích thước object giúp tránh bill Supabase tăng vọt khi traffic viral | Nguồn: webchot.com
Supabase storage RLS: nền tảng policy trước khi mở cổng upload
Phần supabase storage rls là chỗ nhiều team bỏ qua vì muốn demo nhanh, sau đó phải vá policy khi khách hàng hoặc bot quét được URL nhạy cảm. Cách làm sạch nhất: mặc định chặn toàn bộ, chỉ mở incremental. Trong SQL editor hoặc migration, bạn khai báo policy trên storage.objects với các điều kiện auth.role(), auth.uid(), và prefix path ví dụ invoices/{{userId}}/. Nếu bạn lưu thêm bảng attachments ánh xạ bucket,key với owner, bạn có thể join policy để siết chặt hơn so với chỉ dựa vào đường dẫn chuỗi.
Với public asset như banner landing page, hãy tách bucket riêng hoặc prefix public/ và chỉ cho SELECT anonymous. Không reuse bucket private cho ảnh marketing vì dễ nhầm policy DELETE. Log chậm có thể cảnh báo upload bằng service role lộ từ edge function — hạn chế key server chỉ ở biến môi trường và rotate định kỳ. Mình thường yêu cầu team ghi lại bản đồ policy vào một file markdown nội bộ để onboarding dev mới không phải đọc lại cả dashboard.
Tạo bucket, CORS và biến môi trường Supabase cho Next.js
Trước khi viết code upload, hãy chốt ba việc: tên bucket theo môi trường (assets-dev, assets-prod), CORS cho domain preview Vercel và domain chính, và hai biến NEXT_PUBLIC_SUPABASE_URL cùng NEXT_PUBLIC_SUPABASE_ANON_KEY cho client an toàn. Bucket ở production nên bật version nếu bạn cần rollback file pháp lý. Với file lớn, cân nhắc resumable upload hoặc chia chunk — nhưng đa số MVP chỉ cần giới hạn dung lượng phía client và validate MIME type trước.
- Đặt tên bucket theo môi trường: tránh dùng một bucket chung cho dev và prod để không lỡ xoá nhầm object thật.
- CORS chính xác theo domain: thêm cả
https://*.vercel.appnếu bạn preview PR, nhưng không dùng wildcard*trên production. - Giới hạn MIME và kích thước: chặn executable, chỉ cho JPEG/PNG/WebP/PDF theo ngữ cảnh, và báo lỗi thân thiện trên UI.
- Metadata owner: lưu
uploaded_byhoặc path chứa uid để policy RLS đọc được mà không cần join phức tạp.
So sánh phương án lưu file cho MVP và doanh nghiệp nhỏ
Khi bạn còn 200 đơn hàng mỗi tháng, việc chọn đúng phương án lưu file giúp tránh refactor đau đầu sau sáu tháng. Bảng dưới tóm tắt bối cảnh hay gặp khi làm web bán lẻ hoặc portal nội bộ, không nhằm thay thế tư vấn pháp lý về hồ sơ điện tử.
| Tiêu chí | Lựa chọn A | Lựa chọn B | Khuyên dùng |
|---|---|---|---|
| Mức độ nhạy cảm | Public bucket + CDN cache mạnh | Private bucket + signed URL ngắn hạn | Private cho chứng từ, public chỉ cho media marketing |
| Chi phí egress | Ảnh gốc 4K phục vụ zoom | Ảnh biến thể qua transform hoặc resize server | Biến thể theo breakpoint để giữ LCP thấp |
| Kiểm soát truy cập | JWT từ Supabase Auth đủ cho owner | Thêm role admin trong Postgres + policy phức tạp | Bắt đầu JWT đơn giản, mở role khi có audit nội bộ |
| Khả năng di trú | Giữ path logic theo storeId/orderId | Blob ngẫu nhiên khó quản lý thủ công | Path có cấu trúc để migrate sang S3/R2 sau này |
Sau khi đọc bảng, nếu bạn đang làm landing kết hợp catalog nhỏ, hãy ưu tiên public bucket cho hero image đã nén và private cho biên lai chuyển khoản. Điều này giảm số lượng signed URL phát sinh mỗi phiên và vẫn giữ được ranh giới bảo mật rõ ràng.
Quy trình từng bước triển khai upload an toàn trên production
- Bước 1: Tạo bucket trên Supabase Dashboard, ghi chú mục đích từng prefix và môi trường; đồng bộ tên bucket vào biến môi trường Next.js và file migration policy để tái lập local.
- Bước 2: Viết policy RLS tối thiểu cho SELECT/INSERT/DELETE, test bằng hai user giả lập để đảm bảo user A không đọc được object của user B.
- Bước 3: Kết nối Supabase client trên app router với session refresh, tránh để anon key lộ trong code snippet chia sẻ công khai.
- Bước 4: Implement upload function phía client với progress bar và xử lý lỗi MIME; log event thất bại để phát hiện bot upload rác.
- Bước 5: Thiết lập lifecycle xoá file draft, backup định kỳ cho document pháp lý, và dashboard theo dõi dung lượng theo store để tránh bất ngờ cuối tháng.
Khi đủ năm bước, bạn có thể bật analytics Lighthouse và theo dõi LCP ảnh sản phẩm để đảm bảo thay đổi storage không làm landing tụt điểm. Nếu cần CDN ngoài, hãy map cache header rõ ràng để browser tái sử dụng ảnh biến thể.
Chi phí, bảo trì và khi nào nên nhờ dịch vụ triển khai
Dự án SME thường ngầm định storage là phụ đến khi bill egress nhảy vì chiến dịch quảng cáo. Hãy dự phòng 15–20% ngân sách cloud cho media sau khi chạy Meta/Google ads. Nếu team bạn chỉ có một dev và cần ship feature bán hàng trong hai tuần, việc outsource phần kiến trúc Supabase + Next.js có thể rẻ hơn so với downtime vì lỗi policy. Tại Webchốt, gói dịch vụ thiết kế web và triển khai full-stack thường gồm thiết lập bucket, RLS audit, và bàn giao tài liệu vận hành để bạn không phụ thuộc một cá nhân.
Tham chiếu thêm bảng giá linh hoạt nếu bạn muốn tính nhanh phạm vi MVP; các cam kết Lighthouse 100/100, LCP 0.8s và bảo hành 12 tháng giúp bạn đối thoại với chủ doanh nghiệp bằng số liệu thay vì hứa hẹn mơ hồ. Nếu cần template giao diện có sẵn flow upload ảnh sản phẩm, xem catalog template Next.js để rút ngắn thời gian UI.
Sai lầm phổ biến khi cấu hình Supabase Storage lần đầu
Những lỗi dưới đây lặp lại ở cả startup và agency nhỏ; tránh được thì bạn tiết kiệm vài phiên họp khẩn cấp cuối tuần.
- Sai lầm 1: Để bucket private nhưng lại embed URL cố định vào email marketing — khách bấm vào sẽ 403 và nghi ngờ uy tín; hãy dùng signed URL hoặc proxy server kiểm soát phiên.
- Sai lầm 2: Cho phép upload anonymous để “đỡ phải làm auth” — đây là đường ngắn nhất để bucket chứa spam và malware; luôn có captcha hoặc OTP nhẹ.
- Sai lầm 3: Không giới hạn kích thước file phía client khiến mobile yếu bị treo và server phải xử lý hậu kỳ tốn kém; hiển thị giới hạn MB ngay khi chọn file.
- Sai lầm 4: Lưu PDF hoá đơn trong cùng bucket avatar public vì tiện — một policy sai là lộ cả danh sách khách; tách bucket hoặc prefix cứng.
FAQ — hướng dẫn setup supabase storage upload
Public bucket có an toàn nếu chỉ chứa ảnh marketing?
Về cơ bản được, miễn bạn không lưu dữ liệu cá nhân hoặc watermark chứa mã đơn hàng. Vẫn nên bật CDN cache và đặt tên file `/{campaign}/{hash}.webp` để tránh đoán path. Nếu dùng ảnh sản phẩm có metadata EXIF nhạy cảm, hãy strip metadata trước khi upload. Kết hợp chính sách Terms rõ ràng về việc sao chép media để hạn chế competitor scrape hàng loạt mà không có biện pháp kỹ thuật bổ sung.
RLS policy có làm chậm upload hay không?
Policy tối giản không đáng kể so với độ trễ mạng; điểm nghẽn thường là kích thước file và số round trip. Tránh join quá lớn trong policy; nếu cần lookup phức tạp, hãy denormalize cột owner vào metadata object. Benchmark bằng curl và client thật trên 4G để đặt timeout UI hợp lý. Nếu dự án cần upload hàng loạt từ máy quét tại kho, hãy batch nhỏ để tránh lock row metadata.
Next.js App Router nên dùng server action hay client upload?
Client upload phù hợp khi file đi thẳng vào Supabase với session hợp lệ. Server action hữu ích khi bạn phải kiểm tra quota subscription trước khi cho phép PUT. Tránh stream file lớn qua server action chỉ để forward sang Supabase vì tốn bộ nhớ. Pattern Webchốt hay dùng: validate subscription trong server action, trả về short-lived policy hoặc upload token, rồi client gửi tiếp dữ liệu nhị phân trực tiếp.
Làm sao backup object quan trọng mà không tốn kém?
Với volume nhỏ, export định kỳ sang bucket lạnh hoặc lưu bản PDF đã mã hoá trên kho S3 giá rẻ. Với volume lớn, dùng replication của nhà cung cấp và thông báo khi tăng trưởng vượt 30% dự phòng. Ghi rót process restore trong runbook để nhân viên không phải đọc lại toàn bộ Slack cũ khi sự cố xảy ra.
Supabase có thay thế hoàn toàn S3 không?
Với đa số website SME bán hàng và portal nội bộ, Supabase Storage đủ mạnh nếu bạn biết giới hạn egress và tooling transform. Khi bạn streaming video dài hoặc file CAD nặng, cân nhắc hỗn hợp: metadata trong Postgres, binary trong object storage chuyên biệt. Webchốt map kiến trúc hybrid sau khi đo lường kích thước trung bình và tần suất truy cập, tránh over-engineering ngay tuần đầu.
Liên Hệ Webchốt
Để bắt đầu với hướng dẫn setup supabase storage upload trong dự án thật, làm ba việc tuần này: (1) audit bucket và policy hiện tại trên staging, (2) đo LCP của các trang có nhiều ảnh sau khi bật biến thể, (3) chốt ai chịu trách nhiệm rotate key service role và backup file pháp lý. Liên hệ Webchốt qua trang liên hệ, hotline 0905 151 701 hoặc Zalo để được demo concept 48h, bảo hành 12 tháng và hoàn 100% trong 7 ngày nếu phạm vi không khớp — source code 100% thuộc bạn, remote toàn phần.
- Hotline / Zalo: 0905 151 701 — gặp anh Trường (founder/dev).
- Chat Zalo: zalo.me/0905151701 — phản hồi nhanh.
- Email: hi@webchot.com — phản hồi <12h làm việc.
- Studio: 262/1/93 Phan Anh, Phường Phú Thạnh, TP.HCM (T2–T7, 9h–18h).
Tham khảo thêm: 17 template Next.js · 10 dịch vụ web chuyên sâu · bảng giá Webchốt 2026 · 12 công cụ kế toán/tài chính miễn phí.
Reference: Supabase Storage docs · Next.js docs.