{
  "id": 7990305,
  "title": "How I Ship a Controlled Download Site: HTML + Private Object Storage + VPS",
  "url": "https://urgent.news/2026/09/17/how-i-ship-a-controlled-download-site-html-private-object-storage-vps",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-17T08:48:43.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/jiahui_dong_e52833db9f4c1/how-i-ship-a-controlled-download-site-html-private-object-storage-vps-24f7"
  },
  "original_language": "en",
  "account": "This article discusses how to create a secure download site using a combination of HTML, private object storage, and a virtual private server (VPS). The article walks through each step of the process, from acceptance criteria to deployment, and highlights common pitfalls to avoid.\n\nFirst, it's important to agree on the project requirements before any coding begins. This includes defining what constitutes a successful download, how long signed URLs should be valid, and how to prevent secrets from being exposed in the browser. It's also essential to ensure that chat applications do not cache previous versions of the page.\n\nThe front-end of the site consists of a download center-like design with desktop and mobile versions. The download page includes a POST request to generate a download URL, while the FAQ page locks in installation instructions with screenshots. Support information is also provided, including regional contacts.\n\nTo store the download binaries securely, they should not be hosted directly on the VPS. Instead, they should be placed in a private object bucket, such as Qiniu, and accessed through signed URLs. This approach helps control bandwidth and prevent unauthorized access. The backend, built with Flask, handles API requests for generating download URLs and retrieving health status.\n\nAfter uploading binaries to the object storage, the backend exposes a POST endpoint for creating download URLs based on the client's type (PC or Android). The front-end navigates to the returned URL, and the download begins. The API also includes a health check endpoint for smoke testing deploys.\n\nA small VPS, running Ubuntu LTS and configured with only SSH access, is sufficient for this project. The DNS A record should point to the VPS's public IP address. If the client owns the domain, they can update the DNS record; otherwise, a temporary domain or IP can be used initially.\n\nTo deploy the application, clone the repository, set up a virtual environment, install dependencies, configure environment variables, and run the application using either the development server (Flask) or a production-ready server like Gunicorn. Nginx should be used as a reverse proxy in production, with HTTPS enabled using Certbot.\n\nAfter deployment, it's essential to monitor the application's health and address any issues promptly. Common problems include wrong object keys, domain vs. CDN domain mismatches, and in-app caching. These issues can often be resolved by ensuring that the correct file paths are used, renewing SSL certificates before they expire, and properly configuring caching headers on HTML pages.\n\nIn summary, creating a secure download site involves careful planning, building the front-end, securing object storage, and deploying the application on a VPS. By following best practices and addressing potential pitfalls, such as handling expired links and managing in-app caching, developers can create a reliable and efficient download service.",
  "summary": "This article was first published on my site: https://resume.tensorview.cc/blog/secure-download-site-flask-qiniu.html This is the real flow I used — front-end page, private object-storage URLs, then a VPS. Screenshots are from an anonymized demo brand. Your outline is right: page → object storage → wire uploads → rent a VPS → git and run. What usually fails in freelance delivery is not “can you…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}