{"id":24794,"date":"2026-06-02T09:41:20","date_gmt":"2026-06-02T09:41:20","guid":{"rendered":"https:\/\/umang.pk\/2026\/06\/02\/%d8%a7%d8%b3%d9%b9%db%8c%d8%ac%d9%86%da%af-%d8%b3%d8%b1%d9%88%d8%b1-%d9%be%d8%b1-minio-%da%a9%d8%a7-%d8%a7%d8%b3%d8%aa%d8%b9%d9%85%d8%a7%d9%84-%da%a9%d8%b1%d8%aa%db%92-%db%81%d9%88%d8%a6%db%92-s3\/"},"modified":"2026-06-02T09:41:22","modified_gmt":"2026-06-02T09:41:22","slug":"%d8%a7%d8%b3%d9%b9%db%8c%d8%ac%d9%86%da%af-%d8%b3%d8%b1%d9%88%d8%b1-%d9%be%d8%b1-minio-%da%a9%d8%a7-%d8%a7%d8%b3%d8%aa%d8%b9%d9%85%d8%a7%d9%84-%da%a9%d8%b1%d8%aa%db%92-%db%81%d9%88%d8%a6%db%92-s3","status":"publish","type":"post","link":"https:\/\/umang.pk\/ur\/2026\/06\/02\/%d8%a7%d8%b3%d9%b9%db%8c%d8%ac%d9%86%da%af-%d8%b3%d8%b1%d9%88%d8%b1-%d9%be%d8%b1-minio-%da%a9%d8%a7-%d8%a7%d8%b3%d8%aa%d8%b9%d9%85%d8%a7%d9%84-%da%a9%d8%b1%d8%aa%db%92-%db%81%d9%88%d8%a6%db%92-s3\/","title":{"rendered":"\u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0633\u0631\u0648\u0631 \u067e\u0631 MinIO \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 S3 \u06a9\u06d2 \u0645\u0648\u0627\u0641\u0642 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u06cc \u062e\u0648\u062f \u0645\u06cc\u0632\u0628\u0627\u0646\u06cc \u06a9\u06cc\u0633\u06d2 \u06a9\u0631\u06cc\u06ba (\u0627\u0648\u0631 \u0645\u0627\u06c1\u0627\u0646\u06c1 \u0633\u06cc\u0646\u06a9\u0691\u0648\u06ba \u0688\u0627\u0644\u0631 \u0628\u0686\u0627\u0626\u06cc\u06ba)"},"content":{"rendered":"\n<div id=\"\">\n<p>\u06cc\u06c1 \u0645\u0636\u0645\u0648\u0646 HTTPS\u060c \u06a9\u0633\u0679\u0645 \u0688\u0648\u0645\u06cc\u0646\u0632\u060c \u0627\u0648\u0631 \u0635\u0631\u0641 Docker Compose \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 \u0627\u067e \u0644\u0648\u0688\/\u0688\u0627\u0624\u0646 \u0644\u0648\u0688 URLs \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 Traefik \u06a9\u06d2 \u067e\u06cc\u0686\u06be\u06d2 MinIO \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 \u06a9\u0627\u067e\u06cc \u067e\u06cc\u0633\u0679 \u06af\u0627\u0626\u06cc\u0688 \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u067e \u06a9\u06cc \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u0646\u0638\u0645 S3\/Cloudflare R2\/Hetzner \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u06d2 \u06af\u06cc\u060c \u062c\u0628\u06a9\u06c1 \u062a\u0645\u0627\u0645 \u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 \u0627\u067e \u0644\u0648\u0688\u0632\u060c \u0688\u0627\u0624\u0646 \u0644\u0648\u0688\u0632 \u0627\u0648\u0631 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 URLs \u06a9\u0648 \u0622\u067e \u06a9\u06d2 \u067e\u0631 \u0627\u0633\u0679\u0648\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 <strong>\u0627\u067e\u0646\u06d2<\/strong> \u0633\u0631\u0648\u0631 \u0645\u0641\u062a \u0641\u0631\u0627\u06c1\u0645 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-table-of-contents\">\u0627\u0646\u0688\u06cc\u06a9\u0633<\/h2>\n<h2 id=\"heading-1-why-selfhost-object-storage-on-staging\">1. \u0633\u0679\u06cc\u062c\u0646\u06af \u06a9\u0648 \u062e\u0648\u062f \u0645\u06cc\u0632\u0628\u0627\u0646 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06a9\u06cc\u0648\u06ba \u06c1\u06d2\u061f<\/h2>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u06cc \u0627\u06cc\u067e \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a (PDFs\u060c \u067e\u0631\u0648\u0641\u0627\u0626\u0644 \u067e\u06a9\u0686\u0631\u0632\u060c \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06c1\u0633\u0679\u0631\u06cc\u060c \u0631\u06cc\u06a9\u0627\u0631\u0688\u0646\u06af\u0632) \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u06a9\u06cc QA \u0679\u06cc\u0645 \u06a9\u06d2 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u062f\u06c1 \u06c1\u0631 \u0679\u06cc\u0633\u0679 \u06a9\u06d2 \u062d\u0642\u06cc\u0642\u06cc \u0627\u062e\u0631\u0627\u062c\u0627\u062a AWS S3\u060c Cloudflare R2\u060c \u06cc\u0627 Hetzner Object Storage \u0645\u06cc\u06ba \u06c1\u0648\u06ba \u06af\u06d2\u06d4 \u0627\u06af\u0631\u0686\u06c1 \u0641\u06cc \u0641\u0627\u0626\u0644 \u06a9\u06cc \u0642\u06cc\u0645\u062a \u0645\u0639\u0645\u0648\u0644\u06cc \u06c1\u06d2\u060c \u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0622\u067e \u06a9\u0648 \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u06cc \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p>\u06c1\u0632\u0627\u0631\u0648\u06ba \u0688\u0645\u06cc \u0641\u0627\u0626\u0644\u0648\u06ba \u06a9\u0648 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0627\u06cc\u0646\u0688 \u0679\u0648 \u0627\u06cc\u0646\u0688 \u0679\u06cc\u0633\u0679 \u0686\u0644\u0627\u0626\u06cc\u06ba\u060c<\/p>\n<\/li>\n<li>\n<p>\u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u06a9\u0648 \u0631\u0627\u062a \u06a9\u06d2 \u0648\u0642\u062a \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba (\u06cc\u062a\u06cc\u0645 \u0627\u0634\u06cc\u0627\u0621 \u06a9\u0648 \u067e\u06cc\u0686\u06be\u06d2 \u0686\u06be\u0648\u0691 \u06a9\u0631)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0688\u0648\u06cc\u0644\u067e\u0631 \u0627\u0633\u06cc \u0641\u0627\u0626\u0644 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631 \u06a9\u06d2 \u0679\u0648\u0679\u06d2 \u06c1\u0648\u0626\u06d2 \u06a9\u0648\u0688 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062a\u062c\u0631\u0628\u06c1 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06c1\u0645 \u0645\u06c1\u06cc\u0646\u0648\u06ba \u06a9\u06d2 \u0679\u06cc\u0633\u0679 \u0688\u06cc\u0679\u0627 \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u06a9\u0628\u06be\u06cc \u062d\u0630\u0641 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0639\u0645\u0644 \u0645\u06cc\u06ba \u06cc\u06c1 \u0627\u062e\u0631\u0627\u062c\u0627\u062a \u062c\u0627\u0626\u0632 \u06c1\u06cc\u06ba\u06d4 \u0645\u0646\u0638\u0645 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u0646\u0642\u0644\u060c \u062f\u0633\u062a\u06cc\u0627\u0628\u06cc\u060c \u0627\u0648\u0631 \u06a9\u0633\u06cc \u0627\u0648\u0631 \u06a9\u0627 \u067e\u06cc\u062c\u0631 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062a\u06cc\u0627\u0631\u06cc \u0645\u06cc\u06ba \u06cc\u06c1 \u0627\u062e\u0631\u0627\u062c\u0627\u062a \u062e\u0627\u0644\u0635 \u0641\u0636\u0644\u06c1 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>MiniIO<\/strong> \u0627\u06cc\u06a9 \u0645\u0641\u062a \u0627\u0648\u0631 \u0627\u0648\u067e\u0646 \u0633\u0648\u0631\u0633 S3 \u06c1\u0645 \u0622\u06c1\u0646\u06af \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0633\u0631\u0648\u0631\u06d4 \u0648\u06c1\u06cc API\u060c \u0648\u06c1\u06cc SDK\u060c \u0648\u06c1\u06cc \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 URL\u060c \u0648\u06c1\u06cc <code>mc<\/code>\/<code>aws s3<\/code> CLI &#8211; \u0622\u067e \u06a9\u06d2 \u0627\u067e\u0646\u06d2 VPS \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u06a9\u06cc \u0642\u06cc\u0645\u062a $0 \u0641\u06cc \u06af\u06cc\u06af\u0627 \u0628\u0627\u0626\u0679 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e MinIO \u06a9\u0648 \u0627\u067e\u0646\u06cc \u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0627\u06cc\u067e \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0648\u0631 S3\/R2 \u06a9\u0648 \u0627\u067e\u0646\u06cc \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0627\u06cc\u067e \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0635\u0631\u0641 \u0648\u06c1\u06cc \u0686\u06cc\u0632\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba \u062c\u0648 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0646\u062a\u06cc\u062c\u06c1:<\/strong> \u062f\u0648\u0646\u0648\u06ba \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u06a9\u0648\u0688 \u06a9\u0627 \u0631\u0627\u0633\u062a\u06c1\u060c \u0627\u0633\u0679\u06cc\u062c \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u06cc \u06a9\u0648\u0626\u06cc \u0642\u06cc\u0645\u062a \u0646\u06c1\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0627 \u06a9\u0644\u0627\u0624\u0688 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06c1 \u0628\u0627\u06c1\u0631 \u0686\u0644\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u0627\u0686\u06be\u0627 \u0641\u0627\u0644 \u0628\u06cc\u06a9\u06d4<\/p>\n<h2 id=\"heading-2-the-architecture-production-vs-staging\">2. \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631: \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0627\u0648\u0631 \u0627\u0633\u0679\u06cc\u062c\u0646\u06af<\/h2>\n<p>\u062d\u0642\u06cc\u0642\u06cc \u062f\u0646\u06cc\u0627 \u06a9\u06cc \u0627\u06cc\u067e\u0644\u06cc \u06a9\u06cc\u0634\u0646\u0632 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0646\u06c1\u06cc\u06ba \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u067e \u06a9\u06cc \u062a\u0631\u0642\u06cc \u06cc\u0627 \u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0645\u0627\u062d\u0648\u0644 \u06a9\u0648 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u0645\u06cc\u06ba \u0644\u06a9\u06be\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/p>\n<p>\u0639\u0627\u0645 \u0627\u0648\u0631 \u0633\u0631\u0645\u0627\u06cc\u06c1 \u06a9\u0627\u0631\u06cc \u0645\u0624\u062b\u0631 \u0633\u06cc\u0679 \u0627\u067e \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba:<\/p>\n<p>\u0627\u0686\u06be\u06cc \u0628\u0627\u062a \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u0627 \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u0648\u0688 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>\u062c\u0628 \u062a\u06a9 \u062f\u0648\u0646\u0648\u06ba \u0633\u0631\u0648\u0633\u0632 S3 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0637\u0627\u0628\u0642\u062a \u0631\u06a9\u06be\u062a\u06cc \u06c1\u06cc\u06ba\u060c \u0627\u06cc\u06a9 \u06c1\u06cc SDK \u0627\u0648\u0631 \u0627\u067e \u0644\u0648\u0688 \u0645\u0646\u0637\u0642 \u06a9\u06c1\u06cc\u06ba \u0628\u06be\u06cc \u06a9\u0627\u0645 \u06a9\u0631\u06d2 \u06af\u06cc\u06d4 \u0635\u0631\u0641 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u0645\u062e\u062a\u0644\u0641 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-high-level-architecture\">\u0627\u0639\u0644\u06cc \u0633\u0637\u062d\u06cc \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631<\/h3>\n<p>\u0627\u0648\u067e\u0631 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u062e\u0627\u06a9\u06c1 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u062a\u0639\u06cc\u0646\u0627\u062a\u06cc \u06a9\u06d2 \u0645\u0627\u062d\u0648\u0644 \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0645\u062e\u062a\u0644\u0641 \u0633\u0679\u0648\u0631\u06cc\u062c \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06af\u0627\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u06cc\u0633\u06d2 \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u067e\u0631 <strong>\u067e\u06cc\u062f\u0627\u0648\u0627\u0631\u06cc \u0645\u0627\u062d\u0648\u0644<\/strong>\u0627\u067e \u0644\u0648\u0688\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u0645\u0646\u0638\u0645 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u0633\u0631\u0648\u0633 \u062c\u06cc\u0633\u06d2 AWS S3\u060c Cloudflare R2\u060c \u06cc\u0627 Hetzner Object Storage \u0645\u06cc\u06ba \u0645\u062d\u0641\u0648\u0638 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062e\u062f\u0645\u0627\u062a \u067e\u0627\u0626\u06cc\u062f\u0627\u0631\u06cc\u060c \u0627\u0633\u06a9\u06cc\u0644 \u0627\u06cc\u0628\u0644\u0679\u06cc\u060c \u0628\u06cc\u06a9 \u0627\u067e \u0627\u0648\u0631 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06d2 \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0645 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u067e\u0631 <strong>\u0633\u0679\u06cc\u062c\u0646\u06af \u0645\u0627\u062d\u0648\u0644<\/strong>\u0627\u067e \u0644\u0648\u0688\u0632 \u06a9\u0648 \u0622\u067e \u06a9\u06d2 VPS \u067e\u0631 Docker \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062e\u0648\u062f \u0645\u06cc\u0632\u0628\u0627\u0646 MinIO \u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0631\u0648\u0679 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 MinIO \u0644\u0627\u06af\u062a \u06a9\u0648 \u06a9\u0645 \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u06cc \u0637\u0631\u062d \u06a9\u0627\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 S3 API \u06a9\u0648 \u0644\u0627\u06af\u0648 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0648\u0646\u0648\u06ba \u0633\u0679\u0648\u0631\u06cc\u062c \u0633\u0633\u0679\u0645 S3 \u06a9\u06d2 \u0645\u0648\u0627\u0641\u0642 \u06c1\u06cc\u06ba\u060c \u0644\u06c1\u0630\u0627 \u0622\u067e \u06a9\u06cc \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u062a\u0645\u0627\u0645 \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u0627\u067e \u0644\u0648\u0688 \u0645\u0646\u0637\u0642 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0641\u0631\u0642 \u0635\u0631\u0641 \u0645\u0627\u062d\u0648\u0644 \u06a9\u06d2 \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062f\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-why-this-architecture-is-useful\">\u06cc\u06c1 \u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u06cc\u0648\u06ba \u0645\u0641\u06cc\u062f \u06c1\u06d2\u06d4<\/h3>\n<p>\u06cc\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p>\u0633\u0633\u062a\u06cc \u0633\u0679\u06cc\u062c\u0646\u06af \u0645\u0627\u062d\u0648\u0644<\/p>\n<\/li>\n<li>\n<p>\u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u06a9\u06cc \u0637\u0631\u062d \u06a9\u06cc \u062c\u0627\u0646\u0686<\/p>\n<\/li>\n<li>\n<p>\u0632\u06cc\u0631\u0648 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u0648\u06cc\u0646\u0688\u0631 \u0644\u0627\u06a9 \u0627\u0646<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u0648\u0688 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u06a9\u06be\u06d2 \u0628\u063a\u06cc\u0631 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06af\u0627\u0646 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u06c1\u0644\u06cc\u062a<\/p>\n<\/li>\n<\/ul>\n<p>\u062f\u0648\u0646\u0648\u06ba \u0645\u0627\u062d\u0648\u0644 S3 \u067e\u0631\u0648\u0679\u0648\u06a9\u0648\u0644 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06c1\u0630\u0627 \u0627\u067e \u0644\u0648\u0688 \u06a9\u06cc \u0645\u0646\u0637\u0642 \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u06cc \u0631\u06c1\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-example-environment-variables\">\u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631 \u06a9\u06cc \u0645\u062b\u0627\u0644<\/h3>\n<p>\u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0635\u0631\u0641 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0645\u0627\u062d\u0648\u0644\u06cc\u0627\u062a\u06cc \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u06a9\u0648 \u067e\u0691\u06be\u062a\u06cc \u06c1\u06d2:<\/p>\n<pre><code class=\"language-xml\">S3_ENDPOINT=\nS3_REGION=\nS3_ACCESS_KEY=\nS3_SECRET_KEY=\nS3_BUCKET=\n<\/code><\/pre>\n<p>\u0627\u0642\u062f\u0627\u0631 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2\u060c \u0648\u06c1\u06cc \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0627\u0628 \u0641\u0627\u0626\u0644 \u06a9\u0648 \u0645\u062e\u062a\u0644\u0641 \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688 \u067e\u0631 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u06d2 \u06af\u06cc\u06d4<\/p>\n<h3 id=\"heading-production-storage-example\">\u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u06cc \u0645\u062b\u0627\u0644<\/h3>\n<p>\u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0645\u06cc\u0646\u06cc\u062c\u0688 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba:<\/p>\n<ul>\n<li>\n<p>AWS S3<\/p>\n<\/li>\n<li>\n<p>Cloudflare R2<\/p>\n<\/li>\n<li>\n<p>\u06c1\u06cc\u0679\u0632\u0646\u0631 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c<\/p>\n<\/li>\n<\/ul>\n<p>\u06c1\u0627\u06ba:<\/p>\n<pre><code class=\"language-plaintext\">S3_ENDPOINT=https:\/\/<region>.r2.cloudflarestorage.com\n<\/region><\/code><\/pre>\n<p>\u0641\u0648\u0627\u0626\u062f \u06cc\u06c1 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06cc\u06c1 \u0627\u0646\u062a\u06c1\u0627\u0626\u06cc \u0642\u0627\u0628\u0644 \u062a\u0648\u0633\u06cc\u0639 \u06c1\u06d2\u060c \u0639\u0627\u0644\u0645\u06cc \u0633\u0637\u062d \u067e\u0631 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06d2\u060c \u067e\u0627\u0626\u06cc\u062f\u0627\u0631 \u06c1\u06d2\u060c \u0628\u06cc\u06a9 \u0627\u067e \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0688\u06be\u0627\u0646\u0686\u06d2 \u06a9\u06cc \u062f\u06cc\u06a9\u06be \u0628\u06be\u0627\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-staging-environment-example\">\u0633\u0679\u06cc\u062c\u0646\u06af \u0645\u0627\u062d\u0648\u0644 \u06a9\u06cc \u0645\u062b\u0627\u0644<\/h3>\n<p>\u0633\u0679\u06cc\u062c\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u06c1\u0644\u06a9\u06d2 \u0648\u0632\u0646 \u06a9\u06d2 \u062e\u0648\u062f \u0645\u06cc\u0632\u0628\u0627\u0646 MinIO \u06a9\u0646\u0679\u06cc\u0646\u0631\u0632 \u0627\u06a9\u062b\u0631 \u06a9\u0627\u0641\u06cc \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-plaintext\">Next.js App\n     \u2193\nMinIO Container (inside Docker on VPS)\n<\/code><\/pre>\n<p>\u0645\u062b\u0627\u0644 \u0688\u0648\u0645\u06cc\u0646:<\/p>\n<p>\u06cc\u06c1 \u0622\u067e \u06a9\u0648 \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2:<\/p>\n<h2 id=\"heading-3-prerequisites\">3. \u0634\u0631\u0637\u06cc\u06ba<\/h2>\n<p>\u0622\u067e \u06a9\u0648 \u0636\u0631\u0648\u0631\u062a \u06c1\u0648 \u06af\u06cc:<\/p>\n<ul>\n<li>\n<p>Linux VPS (Hetzner\u060c DigitalOcean\u060c Contabo\u060c OVH \u2014 \u0639\u0648\u0627\u0645\u06cc IP \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0686\u06be \u0628\u06be\u06cc)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0633 \u0622\u0626\u06cc \u067e\u06cc \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u062f\u0648 A \u0631\u06cc\u06a9\u0627\u0631\u0688 (\u06c1\u0645 \u0627\u0646\u06c1\u06cc\u06ba \u0627\u06af\u0644\u06cc \u0631\u062c\u0633\u0679\u0631 \u06a9\u0631\u06cc\u06ba \u06af\u06d2)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0688\u0648\u06a9\u0631 + \u0688\u0648\u06a9\u0631 \u06a9\u0645\u067e\u0648\u0632 v2\u06d4<\/p>\n<\/li>\n<li>\n<p>Traefik v2 \u062c\u0633 \u0645\u06cc\u06ba Let&#8217;s Encrypt \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 (\u062a\u0645\u0627\u0645 \u0631\u06cc\u0648\u0631\u0633 \u067e\u0631\u0627\u06a9\u0633\u06cc \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba &#8211; \u0646\u06cc\u0686\u06d2 \u062f\u06cc\u06d2 \u06af\u0626\u06d2 \u0644\u06cc\u0628\u0644 Traefik \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06c1\u06cc\u06ba)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u06be\u0644\u06cc \u0628\u0646\u062f\u0631\u06af\u0627\u06c1 <code>80<\/code> \u0627\u0648\u0631 <code>443<\/code> Let&#8217;s Encrypt + HTTPS \u06a9\u06d2 \u0644\u06cc\u06d2 \u0641\u0627\u0626\u0631 \u0648\u0627\u0644 \u0645\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>MinIO \u0688\u06cc\u0679\u0627 \u0648\u0627\u0644\u06cc\u0648\u0645 \u0634\u0631\u0648\u0639 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 10 GB \u062a\u06a9 \u0645\u0641\u062a \u0688\u0633\u06a9\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u06af\u0631 \u0688\u0648\u06a9\u0631 \u0627\u0646\u0633\u0679\u0627\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2:<\/p>\n<pre><code class=\"language-bash\">curl -fsSL https:\/\/get.docker.com | sh\nsudo apt-get install -y docker-compose-plugin\ndocker --version && docker compose version\n<\/code><\/pre>\n<h2 id=\"heading-4-step-1-dns-point-your-domains-to-the-staging-server\">4. \u0645\u0631\u062d\u0644\u06c1 1 &#8211; DNS: \u0627\u067e\u0646\u06d2 \u0688\u0648\u0645\u06cc\u0646 \u06a9\u0648 \u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0633\u0631\u0648\u0631 \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0622\u067e \u06a9\u06d2 DNS \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0646\u0646\u062f\u06c1 \u0633\u06d2 \u062f\u0648 (Cloudflare\u060c Route 53\u060c Namecheap\u060c \u0648\u063a\u06cc\u0631\u06c1) <strong>\u0627\u06cc\u06a9 \u0631\u06cc\u06a9\u0627\u0631\u0688<\/strong> \u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0633\u0631\u0648\u0631 \u06a9\u06d2 \u0639\u0648\u0627\u0645\u06cc IP \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-plaintext\">minio-staging.domain.com           A    203.0.113.45\nminio-console-staging.domain.com   A    203.0.113.45\n<\/code><\/pre>\n<p>\u0627\u06af\u0631 \u0622\u067e Cloudflare \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0627\u067e\u0646\u06cc \u067e\u0631\u0627\u06a9\u0633\u06cc \u0627\u0633\u0679\u06cc\u0679\u0633 \u06a9\u0648 \u0627\u0633 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba: <strong>\u0635\u0631\u0641 DNS<\/strong> (\u0633\u0631\u0645\u0626\u06cc \u0628\u0627\u062f\u0644) <code>minio-staging.*<\/code>. Cloudflare \u06a9\u0627 \u0645\u0641\u062a \u0645\u0646\u0635\u0648\u0628\u06c1 \u0627\u067e \u0644\u0648\u0688\u0632 \u06a9\u0648 100MB \u062a\u06a9 \u0645\u062d\u062f\u0648\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u0686\u0627\u06c1\u062a\u0627 \u06a9\u06c1 \u0622\u067e S3 \u062f\u0633\u062a\u062e\u0637\u06cc \u06c1\u06cc\u0688\u0631 \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u0622\u067e \u0627\u067e\u0646\u06d2 WAF \u06a9\u0648 \u0633\u0627\u0645\u0646\u06d2 \u0644\u0627\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0622\u067e \u0627\u067e\u0646\u06d2 \u06a9\u0646\u0633\u0648\u0644 \u06a9\u06d2 \u0630\u06cc\u0644\u06cc \u0688\u0648\u0645\u06cc\u0646 \u06a9\u0648 \u067e\u0631\u0627\u06a9\u0633\u06cc\u0688 \u0631\u06a9\u06be \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0627\u06cc\u06a9 \u0644\u0645\u062d\u06c1 \u0627\u0646\u062a\u0638\u0627\u0631 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">dig +short minio-staging.domain.com\n# 203.0.113.45\n<\/code><\/pre>\n<h2 id=\"heading-5-step-2-run-minio-with-docker-compose\">5. \u0645\u0631\u062d\u0644\u06c1 2 &#8211; \u0688\u0648\u06a9\u0631 \u06a9\u0645\u067e\u0648\u0632 \u06a9\u06d2 \u0633\u0627\u062a\u06be MinIO \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4<\/h2>\n<p>\u0622\u067e \u0627\u0633 \u0633\u0631\u0648\u0633 \u06a9\u0648 \u0633\u0679\u06cc\u062c\u0646\u06af \u062a\u062e\u0644\u06cc\u0642 \u0641\u0627\u0626\u0644 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba (<code>docker-compose.staging.yml<\/code>)\u06d4 MinIO \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u06a9\u0646\u0679\u06cc\u0646\u0631 \u06c1\u06d2\u06d4 \u0688\u0633\u06a9 \u06a9\u0648 \u0688\u0648\u06a9\u0631 \u0648\u0627\u0644\u06cc\u0648\u0645 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0635\u0628 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0627\u067e \u06af\u0631\u06cc\u0688 \u06a9\u06d2 \u0628\u0639\u062f \u0622\u067e \u06a9\u0627 \u0688\u06cc\u0679\u0627 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-yaml\"># docker-compose.staging.yml\nnetworks:\n  proxy:\n    external: true\n    name: proxy\n  internal:\n    name: internal\n\nvolumes:\n  minio-data:\n\nservices:\n  minio:\n    image: minio\/minio:latest\n    container_name: minio-staging\n    restart: unless-stopped\n    environment:\n      - MINIO_ROOT_USER=${MINIO_ROOT_USER:-admin}\n      - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-change-me-please}\n      # Tell MinIO which public domain to sign URLs with\n      - MINIO_SERVER_URL=https:\/\/minio-staging.domain.com\n      - MINIO_BROWSER_REDIRECT_URL=https:\/\/minio-console-staging.domain.com\n    command: server \/data --console-address \":9001\"\n    volumes:\n      - minio-data:\/data\n    networks:\n      - proxy\n      - internal\n    ports:\n      - \"9000:9000\"  # S3 API\n      - \"9001:9001\"  # Web console\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http:\/\/localhost:9000\/minio\/health\/live\"]\n      interval: 10s\n      timeout: 5s\n      retries: 3\n      start_period: 30s\n<\/code><\/pre>\n<p>\u062f\u0648 \u0628\u0627\u062a\u06cc\u06ba \u0642\u0627\u0628\u0644 \u062a\u0648\u062c\u06c1 \u06c1\u06cc\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p><code>MINIO_SERVER_URL<\/code>    \u06cc\u06c1 \u062e\u0641\u06cc\u06c1 \u0686\u0679\u0646\u06cc \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c MinIO \u062f\u0627\u062e\u0644\u06cc \u0645\u06cc\u0632\u0628\u0627\u0646 \u0646\u0627\u0645 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u06d2 \u06af\u0627 (<code>http:\/\/minio:9000<\/code>)\u060c \u062a\u0648\u062b\u06cc\u0642 \u0627\u0633 \u0648\u0642\u062a \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u06cc \u06c1\u06d2 \u062c\u0628 \u0628\u0631\u0627\u0624\u0632\u0631 \u0639\u0648\u0627\u0645\u06cc \u0688\u0648\u0645\u06cc\u0646 \u0633\u06d2 \u0679\u06a9\u0631\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633\u06d2 \u0628\u0627\u0644\u06a9\u0644 \u0648\u06c1\u06cc HTTPS URL \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba \u062c\u0633\u06d2 \u0622\u067e \u06a9\u06d2 \u06a9\u0644\u0627\u0626\u0646\u0679 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><code>MINIO_BROWSER_REDIRECT_URL<\/code>    \u0648\u06cc\u0628 \u06a9\u0646\u0633\u0648\u0644 \u0628\u06be\u06cc \u0627\u06cc\u0633\u0627 \u06c1\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (\u0644\u0627\u06af \u0627\u0646 \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679\u0633\u060c OIDC \u06a9\u0627\u0644 \u0628\u06cc\u06a9\u0633 \u0648\u063a\u06cc\u0631\u06c1)\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0644\u0627\u0626\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">docker compose -f docker-compose.staging.yml up -d minio\ndocker compose -f docker-compose.staging.yml logs -f minio\n<\/code><\/pre>\n<p>\u0622\u067e \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2 <code>API: http:\/\/...<\/code> \u0627\u0648\u0631 <code>Console: http:\/\/...<\/code> \u0633\u0645\u0648\u0686<\/p>\n<h2 id=\"heading-6-step-3-expose-minio-over-https-with-traefik\">6. \u0645\u0631\u062d\u0644\u06c1 3 &#8211; Traefik \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 HTTPS \u067e\u0631 MinIO \u06a9\u0648 \u0628\u06d2 \u0646\u0642\u0627\u0628 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u06c1\u0645 \u0628\u0646\u062f\u0631\u06af\u0627\u06c1\u0648\u06ba \u06a9\u0648 \u0628\u06d2 \u0646\u0642\u0627\u0628 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>9000<\/code>\/<code>9001<\/code> \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u062f\u0646\u06cc\u0627 \u06a9\u06d2 \u0644\u06cc\u06d2 \u2014 Traefik \u06c1\u0645\u0627\u0631\u06d2 \u0644\u06cc\u06d2 \u0645\u0641\u062a Let&#8217;s Encrypt \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679\u0633 \u06a9\u06d2 \u0633\u0627\u062a\u06be TLS \u06a9\u0648 \u062e\u062a\u0645 \u06a9\u0631 \u06a9\u06d2 \u0627\u06cc\u0633\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u0644\u06cc\u0628\u0644 <code>minio<\/code> \u0633\u0631\u0648\u0633:<\/p>\n<pre><code class=\"language-yaml\">    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.docker.network=proxy\"\n\n      # ---- S3 API (port 9000) ----\n      - \"traefik.http.routers.minio-staging.rule=Host(`minio-staging.domain.com`)\"\n      - \"traefik.http.routers.minio-staging.entrypoints=websecure\"\n      - \"traefik.http.routers.minio-staging.tls.certresolver=letsencrypt\"\n      - \"traefik.http.routers.minio-staging.service=minio-staging\"\n      - \"traefik.http.services.minio-staging.loadbalancer.server.port=9000\"\n\n      # ---- Web Console (port 9001) ----\n      - \"traefik.http.routers.minio-console-staging.rule=Host(`minio-console-staging.domain.com`)\"\n      - \"traefik.http.routers.minio-console-staging.entrypoints=websecure\"\n      - \"traefik.http.routers.minio-console-staging.tls.certresolver=letsencrypt\"\n      - \"traefik.http.routers.minio-console-staging.service=minio-console-staging\"\n      - \"traefik.http.services.minio-console-staging.loadbalancer.server.port=9001\"\n<\/code><\/pre>\n<p>\u0622\u067e \u0628\u06be\u06cc <code>entrypoint<\/code> \u06a9\u06d2 \u0644\u06cc\u06d2 <code>:443<\/code> \u0627\u0648\u0631 <code>certificatesresolver<\/code> \u0646\u0627\u0645\u0632\u062f <code>letsencrypt<\/code>. \u06a9\u0645 \u0627\u0632 \u06a9\u0645 Traefik \u062a\u0631\u062a\u06cc\u0628 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u06c1\u06d2 (<code>traefik.staging.yml<\/code>):<\/p>\n<pre><code class=\"language-yaml\">api:\n  dashboard: true\n\nentryPoints:\n  web:\n    address: \":80\"\n  websecure:\n    address: \":443\"\n\ncertificatesResolvers:\n  letsencrypt:\n    acme:\n      httpChallenge:\n        entryPoint: web\n      email: admin@domain.com\n      storage: \/etc\/traefik\/acme.json\n\nproviders:\n  docker:\n    endpoint: \"unix:\/\/\/var\/run\/docker.sock\"\n    exposedByDefault: false\n    network: proxy\n<\/code><\/pre>\n<p>\u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0633\u0631\u0679\u06cc\u0641\u06a9\u06cc\u0679 \u062c\u0627\u0631\u06cc \u06c1\u0648\u062a\u06d2 \u06c1\u06cc \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">docker compose -f docker-compose.staging.yml up -d\ndocker compose -f docker-compose.staging.yml logs -f traefik | grep -i acme\n<\/code><\/pre>\n<p>\u0627\u067e\u0646\u06d2 \u0644\u06cc\u067e \u0679\u0627\u067e \u067e\u0631 \u0627\u0633\u0679\u06cc\u0679\u0633 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\">curl -I https:\/\/minio-staging.domain.com\/minio\/health\/live\n# HTTP\/2 200\n<\/code><\/pre>\n<p>\u0627\u0628 \u0622\u067e \u0627\u06af\u0644\u06cc \u0628\u0627\u0631 \u0644\u0627\u06af \u0627\u0646 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <strong>\u0648\u06cc\u0628 \u06a9\u0646\u0633\u0648\u0644<\/strong> \u06a9\u0648 <code>https:\/\/minio-console-staging.domain.com<\/code> \u06a9\u06d2 \u0633\u0627\u062a\u06be <code>admin<\/code> \/ <code>change-me-please<\/code>.<\/p>\n<p><strong>\u0627\u06c1\u0645 \u0627\u067e \u0644\u0648\u0688 \u0633\u0627\u0626\u0632\u0646\u06af:<\/strong> \u0627\u06af\u0631 \u0622\u067e Traefik \u06a9\u06d2 \u0633\u0627\u0645\u0646\u06d2 Cloudflare \u06cc\u0627 NGINX \u06a9\u06d2 \u067e\u06cc\u0686\u06be\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06cc \u0628\u0627\u0688\u06cc \u06a9\u06cc \u062d\u062f \u0645\u06cc\u06ba \u0627\u0636\u0627\u0641\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 Traefik \u06a9\u06cc \u062e\u0648\u062f \u06a9\u0648\u0626\u06cc \u0688\u06cc\u0641\u0627\u0644\u0679 \u062d\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 Cloudflare \u06a9\u0627 \u0645\u0641\u062a \u0645\u0646\u0635\u0648\u0628\u06c1 100MB \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u06a9\u0648 \u0645\u0633\u062a\u0631\u062f \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0633\u06cc\u0644\u0641 \u06c1\u0648\u0633\u0679\u0688 \u0627\u06cc\u062c \u067e\u0631\u0627\u06a9\u0633\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u062f\u0631\u062c \u0630\u06cc\u0644 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba: <code>client_max_body_size 0;<\/code> (NGINX) \u06cc\u0627 \u0627\u0633 \u06a9\u06d2 \u0645\u0633\u0627\u0648\u06cc\u06d4<\/p>\n<h2 id=\"heading-7-step-4-create-the-bucket-and-access-keys\">7. \u0645\u0631\u062d\u0644\u06c1 4 &#8211; \u0628\u0627\u0644\u0679\u06cc \u0627\u0648\u0631 \u0631\u0633\u0627\u0626\u06cc \u06a9\u0644\u06cc\u062f \u0628\u0646\u0627\u0626\u06cc\u06ba<\/h2>\n<p>S3 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06cc \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 MinIO \u0633\u06d2 \u0628\u0627\u062a \u06a9\u0631 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u06d4 \u0633\u0628 \u0633\u06d2 \u0622\u0633\u0627\u0646 \u0679\u0648\u0644 \u06c1\u06d2\u06d4 <code>mc<\/code> (\u0622\u0641\u06cc\u0634\u0644 MinIO \u06a9\u0644\u0627\u0626\u0646\u0679)\u060c \u0627\u0633\u06cc \u062a\u0635\u0648\u06cc\u0631 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062f\u06c1\u06d4<\/p>\n<h3 id=\"heading-71-connect-mc-to-your-server\">7.1 MC \u06a9\u0648 \u0633\u0631\u0648\u0631 \u0633\u06d2 \u062c\u0648\u0691\u06cc\u06ba\u06d4<\/h3>\n<pre><code class=\"language-bash\">docker exec -it minio-staging \n  mc alias set local http:\/\/localhost:9000 admin change-me-please\n<\/code><\/pre>\n<h3 id=\"heading-72-create-a-bucket\">7.2 \u0628\u0627\u0644\u0679\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba<\/h3>\n<pre><code class=\"language-bash\">docker exec -it minio-staging mc mb local\/domain-files-staging\n<\/code><\/pre>\n<h3 id=\"heading-73-choose-a-bucket-policy\">7.3 \u0628\u0627\u0644\u0679\u06cc \u067e\u0627\u0644\u06cc\u0633\u06cc \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p>\u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u062a\u06cc\u0646 \u0627\u0646\u062a\u062e\u0627\u0628 \u06c1\u06cc\u06ba\u060c \u0644\u06c1\u0630\u0627 \u0622\u067e \u0646\u06d2 \u062c\u0648 \u0645\u062d\u0641\u0648\u0638 \u06a9\u06cc\u0627 \u06c1\u06d2 \u0627\u0633 \u06a9\u06cc \u0628\u0646\u06cc\u0627\u062f \u067e\u0631 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<table>\n<thead>\n<tr>\n<th>\u067e\u0627\u0644\u06cc\u0633\u06cc<\/th>\n<th>\u0645\u06cc\u06ba \u0627\u0633\u06d2 \u06a9\u0628 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0648\u06ba\u061f<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>private<\/code>    (\u0628\u0646\u06cc\u0627\u062f\u06cc)<\/td>\n<td>\u0637\u0627\u0644\u0628 \u0639\u0644\u0645 \u06a9\u06cc \u0646\u0642\u0644\u06cc\u06ba\u060c \u0645\u0639\u0627\u06c1\u062f\u06d2\u060c \u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a\u060c \u06a9\u0686\u06be \u0628\u06be\u06cc \u062d\u0633\u0627\u0633\u06d4 \u0635\u0631\u0641 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 URLs \u0633\u06d2 \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td><code>download<\/code><\/td>\n<td>\u06a9\u06be\u0644\u0627 \u067e\u0691\u06be\u0646\u0627\u060c \u063a\u06cc\u0631 \u0641\u06c1\u0631\u0633\u062a\u06d4 \u0627\u0648\u062a\u0627\u0631 \u062c\u06cc\u0633\u06d2 CDN \u0637\u0631\u0632 \u06a9\u06d2 \u0627\u062b\u0627\u062b\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06c1\u062a\u0631\u06cc\u0646\u06d4<\/td>\n<\/tr>\n<tr>\n<td><code>public<\/code><\/td>\n<td>\u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u067e\u0691\u06be \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0641\u06c1\u0631\u0633\u062a \u0628\u0646\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0635\u0631\u0641 \u062d\u0642\u06cc\u0642\u06cc \u0639\u0648\u0627\u0645\u06cc \u0645\u0648\u0627\u062f \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u0627\u06cc\u06a9 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba:<\/p>\n<pre><code class=\"language-bash\"># Private (recommended for documents)\ndocker exec -it minio-staging \n  mc anonymous set none local\/domain-files-staging\n\n# OR public read for static assets only:\ndocker exec -it minio-staging \n  mc anonymous set download local\/domain-files-staging\n<\/code><\/pre>\n<h3 id=\"heading-74-create-a-dedicated-app-user-dont-use-root-keys\">7.4 \u0633\u0631\u0634\u0627\u0631 \u0627\u06cc\u067e \u0635\u0627\u0631\u0641\u06cc\u0646 \u0628\u0646\u0627\u0626\u06cc\u06ba (\u0631\u0648\u0679 \u06a9\u0644\u06cc\u062f \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba!)<\/h3>\n<p>\u06a9\u06c1 <code>admin<\/code> \u0622\u067e \u06a9\u0627 \u0627\u06a9\u0627\u0624\u0646\u0679 \u06c1\u0631 \u0686\u06cc\u0632 \u0633\u06d2 \u0635\u0627\u0641 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u067e\u0646\u06cc \u0627\u06cc\u067e \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0645 \u0633\u06d2 \u06a9\u0645 \u0645\u0631\u0627\u0639\u0627\u062a \u06cc\u0627\u0641\u062a\u06c1 \u0635\u0627\u0631\u0641 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">docker exec -it minio-staging mc admin user add local \n  domain-app a-long-random-secret-key\n\n# Attach the built-in read\/write policy, scoped to one bucket via JSON:\ncat > \/tmp\/policy.json <<'EOF'\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\"s3:*\"],\n      \"Resource\": [\n        \"arn:aws:s3:::domain-files-staging\",\n        \"arn:aws:s3:::domain-files-staging\/*\"\n      ]\n    }\n  ]\n}\nEOF\n\ndocker cp \/tmp\/policy.json minio-staging:\/tmp\/policy.json\ndocker exec -it minio-staging \n  mc admin policy create local domain-rw \/tmp\/policy.json\ndocker exec -it minio-staging \n  mc admin policy attach local domain-rw --user domain-app\n<\/code><\/pre>\n<p>\u0627\u0646 \u062f\u0648 \u0642\u062f\u0631\u0648\u06ba \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u06a9\u0631\u06cc\u06ba\u06d4 <code>S3_ACCESS_KEY<\/code> \u0627\u0648\u0631 <code>S3_SECRET_KEY<\/code>.<\/p>\n<h2 id=\"heading-8-step-5-configure-your-app-to-use-minio-on-staging-only\">8. \u0645\u0631\u062d\u0644\u06c1 5 - \u0635\u0631\u0641 \u062a\u06cc\u0627\u0631\u06cc \u06a9\u06d2 \u0645\u0631\u062d\u0644\u06d2 \u0645\u06cc\u06ba MinIO \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u067e \u06a9\u0648 \u06a9\u0646\u0641\u06cc\u06af\u0631 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\"\u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0645\u06cc\u06ba MinIO\u060c \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0645\u06cc\u06ba \u062d\u0642\u06cc\u0642\u06cc S3\" \u06a9\u0627 \u0631\u0627\u0632 <strong>\u0627\u06cc\u06a9 \u06c1\u06cc S3 \u06a9\u0644\u0627\u0626\u0646\u0679<\/strong> \u0627\u067e\u0646\u06d2 \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u0635\u0631\u0641 env vars \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0622\u067e \u06a9\u0627 <code>staging.env<\/code> (\u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u062a\u062e\u0644\u06cc\u0642 \u0627\u0633\u0679\u06cc\u06a9 \u0633\u06d2 \u0628\u06be\u0631\u06cc \u06c1\u0648\u0626\u06cc):<\/p>\n<pre><code class=\"language-env\"># ---- Staging: self-hosted MinIO ----\nSTORAGE_ENABLED=true\nS3_ENDPOINT=https:\/\/minio-staging.domain.com\nS3_PUBLIC_ENDPOINT=https:\/\/minio-staging.domain.com\nS3_BUCKET=domain-files-staging\nS3_ACCESS_KEY=domain-app\nS3_SECRET_KEY=a-long-random-secret-key\nS3_REGION=us-east-1\nS3_FORCE_PATH_STYLE=true\n<\/code><\/pre>\n<p>\u0622\u067e \u06a9\u0627 <code>production.env<\/code>:<\/p>\n<pre><code class=\"language-env\"># ---- Production: Cloudflare R2 ----\nSTORAGE_ENABLED=true\nS3_ENDPOINT=https:\/\/<account-id>.r2.cloudflarestorage.com\nS3_PUBLIC_ENDPOINT=https:\/\/files.domain.com\nS3_BUCKET=domain-files\nS3_ACCESS_KEY=<r2-access-key>\nS3_SECRET_KEY=<r2-secret-key>\nS3_REGION=auto\nS3_FORCE_PATH_STYLE=true\n<\/r2-secret-key><\/r2-access-key><\/account-id><\/code><\/pre>\n<p><code>S3_FORCE_PATH_STYLE=true<\/code>    MinIO \u0633\u0628 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06c1\u0645 \u06c1\u06d2\u06d4 <strong>\u0627\u0648\u0631<\/strong> R2\/Hetzner\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c SDK \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06d2 \u06af\u0627: <code>https:\/\/bucket.minio-staging.domain.com<\/code> (\u0648\u0631\u0686\u0648\u0626\u0644 \u06c1\u0648\u0633\u0679 \u0627\u0633\u0679\u0627\u0626\u0644)\u060c \u062d\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0628 \u0622\u067e \u06a9\u06d2 \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u0648\u0688 \u0645\u06cc\u06ba (AWS SDK v3 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 Node.js \u0645\u062b\u0627\u0644):<\/p>\n<pre><code class=\"language-javascript\">\/\/ src\/lib\/s3.js\nimport { S3Client } from \"@aws-sdk\/client-s3\";\n\nexport const s3 = new S3Client({\n  endpoint: process.env.S3_ENDPOINT,\n  region: process.env.S3_REGION,\n  credentials: {\n    accessKeyId: process.env.S3_ACCESS_KEY,\n    secretAccessKey: process.env.S3_SECRET_KEY,\n  },\n  forcePathStyle: process.env.S3_FORCE_PATH_STYLE === \"true\",\n});\n\nexport const BUCKET = process.env.S3_BUCKET;\nexport const PUBLIC_ENDPOINT = process.env.S3_PUBLIC_ENDPOINT;\n<\/code><\/pre>\n<p>\u0627\u06cc\u06a9 \u06c1\u06cc <code>s3<\/code> \u0622\u067e \u06a9\u06cc \u0645\u062b\u0627\u0644 \u0627\u0628 \u0645\u0646\u0627\u0626\u06cc\u0648 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0633\u0679\u06cc\u062c\u0646\u06af \u0645\u06cc\u06ba \u0627\u0648\u0631 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba R2 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u06a9\u0648\u0688 \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06d2 \u0628\u0627\u062a \u0686\u06cc\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-9-step-6-upload-files-3-ways\">9. \u0645\u0631\u062d\u0644\u06c1 6 - \u0641\u0627\u0626\u0644\u06cc\u06ba \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba (3 \u0637\u0631\u06cc\u0642\u06d2)<\/h2>\n<h3 id=\"heading-91-from-a-server-best-for-trusted-backends\">9.1 \u0633\u0631\u0648\u0631 \u067e\u0631 (\u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0628\u06cc\u06a9 \u0627\u06cc\u0646\u0688\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06c1\u062a\u0631\u06cc\u0646)<\/h3>\n<pre><code class=\"language-javascript\">import { PutObjectCommand } from \"@aws-sdk\/client-s3\";\nimport { s3, BUCKET } from \".\/lib\/s3.js\";\nimport { readFile } from \"node:fs\/promises\";\n\nexport async function uploadDocument(localPath, key, contentType) {\n  const Body = await readFile(localPath);\n  await s3.send(new PutObjectCommand({\n    Bucket: BUCKET,\n    Key: key,\n    Body,\n    ContentType: contentType,\n    \/\/ Optional: per-object metadata, useful for audits\n    Metadata: { uploadedBy: \"system\", env: process.env.NODE_ENV },\n  }));\n  return key;\n}\n<\/code><\/pre>\n<h3 id=\"heading-92-with-the-mc-cli-good-for-oneoff-uploads-migrations\">9.2 mc CLI \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 (\u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0627\u067e \u0644\u0648\u0688\/\u0645\u0627\u0626\u06cc\u06af\u0631\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0648\u0632\u0648\u06ba)<\/h3>\n<pre><code class=\"language-bash\">mc alias set staging https:\/\/minio-staging.domain.com domain-app a-long-random-secret-key\nmc cp .\/report.pdf staging\/domain-files-staging\/reports\/2026\/report.pdf\nmc ls staging\/domain-files-staging --recursive\n<\/code><\/pre>\n<h3 id=\"heading-93-directly-from-the-browser-via-a-presigned-put-url\">9.3 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0627\u067e\u0646\u06d2 \u0628\u0631\u0627\u0624\u0632\u0631 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 PUT URL \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2<\/h3>\n<p>\u0635\u0627\u0631\u0641 \u06a9\u06d2 \u0627\u067e \u0644\u0648\u0688\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u062c\u0648\u06cc\u0632 \u06a9\u0631\u062f\u06c1 \u067e\u06cc\u0679\u0631\u0646 \u06cc\u06c1 \u06c1\u06d2: \u0641\u0627\u0626\u0644 \u0622\u067e \u06a9\u06d2 \u0628\u0631\u0627\u0624\u0632\u0631 \u0645\u06cc\u06ba MinIO \u067e\u0631 \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4 <strong>\u0635\u0641\u0631<\/strong> \u06cc\u06c1 \u0648\u06c1 \u0628\u0627\u0626\u0679\u0633 \u06c1\u06cc\u06ba \u062c\u0648 API \u0633\u0631\u0648\u0631 \u06a9\u0648 \u0645\u0627\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06c1\u0645 \u0627\u06af\u0644\u06cc \u0628\u0627\u0631 \u0627\u0633 \u067e\u0631 \u0645\u0632\u06cc\u062f \u062a\u0641\u0635\u06cc\u0644 \u0633\u06d2 \u0628\u0627\u062a \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4<\/p>\n<h2 id=\"heading-10-step-7-generate-presigned-urls-put-and-get\">10. \u0645\u0631\u062d\u0644\u06c1 7 - \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 URLs \u0628\u0646\u0627\u0626\u06cc\u06ba (PUT \u0627\u0648\u0631 GET)<\/h2>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <strong>\u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 URL<\/strong> \u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 HTTPS URL \u062c\u0633 \u0645\u06cc\u06ba \u0627\u0633\u062a\u0641\u0633\u0627\u0631 \u06a9\u06d2 \u0627\u0633\u0679\u0631\u0646\u06af \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0648\u0642\u062a \u0645\u062d\u062f\u0648\u062f \u062f\u0633\u062a\u062e\u0637 \u06c1\u06d2\u06d4 URL \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0634\u062e\u0635 \u0627\u06af\u0644\u06d2 N \u0645\u0646\u0679 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u0627\u0644\u06a9\u0644 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 \u0622\u067e\u0631\u06cc\u0634\u0646 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 (\u0627\u0633 \u0686\u06cc\u0632 \u06a9\u0648 \u0688\u0627\u0644\u06cc\u06ba \u06cc\u0627 \u0627\u0633 \u0686\u06cc\u0632 \u06a9\u0648 \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba) \u0627\u0648\u0631 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0648\u06c1\u06cc \u06c1\u06d2 \u062c\u0648 \"\u0635\u0627\u0631\u0641 \u06a9\u0648 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u067e\u0631 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\" \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-101-presigned-put-for-uploads\">10.1 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 PUT (\u0627\u067e \u0644\u0648\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2)<\/h3>\n<pre><code class=\"language-javascript\">\/\/ src\/lib\/presign.js\nimport { PutObjectCommand, GetObjectCommand } from \"@aws-sdk\/client-s3\";\nimport { getSignedUrl } from \"@aws-sdk\/s3-request-presigner\";\nimport { s3, BUCKET } from \".\/s3.js\";\nimport { randomUUID } from \"node:crypto\";\n\nexport async function presignUpload({ filename, contentType, userId }) {\n  const key = `users\/({userId}\/){randomUUID()}-${filename}`;\n  const cmd = new PutObjectCommand({\n    Bucket: BUCKET,\n    Key: key,\n    ContentType: contentType,\n  });\n  const uploadUrl = await getSignedUrl(s3, cmd, { expiresIn: 60 * 5 }); \/\/ 5 min\n  return { uploadUrl, key };\n}\n<\/code><\/pre>\n<p>\u06c1\u0645\u0627\u0631\u06d2 API \u0633\u06d2 \u062c\u0691\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-javascript\">\/\/ POST \/api\/uploads\/presign\napp.post(\"\/api\/uploads\/presign\", requireAuth, async (req, res) => {\n  const { filename, contentType } = req.body;\n  const result = await presignUpload({\n    filename,\n    contentType,\n    userId: req.user.id,\n  });\n  res.json(result); \/\/ { uploadUrl, key }\n});\n<\/code><\/pre>\n<p>\u0628\u0631\u0627\u0624\u0632\u0631 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a MinIO \u067e\u0631 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-javascript\">\/\/ In your frontend\nasync function uploadFile(file) {\n  const { uploadUrl, key } = await fetch(\"\/api\/uploads\/presign\", {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application\/json\" },\n    body: JSON.stringify({ filename: file.name, contentType: file.type }),\n  }).then(r => r.json());\n\n  await fetch(uploadUrl, {\n    method: \"PUT\",\n    headers: { \"Content-Type\": file.type },\n    body: file,\n  });\n\n  \/\/ Persist `key` in your DB so you can retrieve it later\n  await fetch(\"\/api\/documents\", {\n    method: \"POST\",\n    body: JSON.stringify({ key, originalName: file.name }),\n  });\n}\n<\/code><\/pre>\n<p>\u06a9\u06c1 <code>Content-Type<\/code> PUT \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0628\u06be\u06cc\u062c\u062a\u06d2 \u0648\u0642\u062a <strong>\u0645\u0644\u0646\u0627 \u0686\u0627\u06c1\u0626\u06d2<\/strong> \u0628\u0635\u0648\u0631\u062a \u062f\u06cc\u06af\u0631 MinIO \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0648 \u0645\u0633\u062a\u0631\u062f \u06a9\u0631 \u062f\u06d2 \u06af\u0627\u06d4 <code>SignatureDoesNotMatch<\/code>. \u06cc\u06c1 \u067e\u06c1\u0644\u06cc \u0628\u0627\u0631 \u0633\u0628 \u06a9\u0648 \u067e\u06a9\u0691\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-102-presigned-get-for-downloads\">10.2 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 GET (\u0688\u0627\u0624\u0646 \u0644\u0648\u0688 \u06a9\u06d2 \u0644\u06cc\u06d2)<\/h3>\n<p>\u062d\u0627\u0644\u0627\u0646\u06a9\u06c1 \u0645\u06cc\u06ba \u0628\u06be\u06cc \u06cc\u06c1\u06cc \u0633\u0648\u0686\u062a\u0627 \u06c1\u0648\u06ba\u06d4 <code>GetObjectCommand<\/code>:<\/p>\n<pre><code class=\"language-javascript\">export async function presignDownload(key, expiresIn = 60 * 10) {\n  const cmd = new GetObjectCommand({ Bucket: BUCKET, Key: key });\n  return getSignedUrl(s3, cmd, { expiresIn });\n}\n<\/code><\/pre>\n<p>\u0639\u0627\u0645 \"\u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u062f\u06cc\u06a9\u06be\u06cc\u06ba\" \u06a9\u06d2 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u06a9\u0627\u062a:<\/p>\n<pre><code class=\"language-javascript\">app.get(\"\/api\/documents\/:id\/url\", requireAuth, async (req, res) => {\n  const doc = await db.documents.findById(req.params.id);\n  if (!doc || !canUserSee(req.user, doc)) return res.sendStatus(403);\n  const url = await presignDownload(doc.key, 600);\n  res.json({ url });\n});\n<\/code><\/pre>\n<p>\u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u0627\u0633 URL \u06a9\u0648 \u06a9\u06be\u0648\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0641\u0627\u0626\u0644\u0648\u06ba \u06a9\u0648 MinIO \u0633\u06d2 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0635\u0627\u0631\u0641 \u062a\u06a9 \u067e\u06c1\u0646\u0686\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-103-why-presigned-urls-beat-proxy-through-the-api\">10.3 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 URL \u06a9\u06cc\u0648\u06ba \"\u067e\u0631\u0627\u06a9\u0633\u06cc \u0628\u0630\u0631\u06cc\u0639\u06c1 API\" \u0633\u06d2 \u0628\u06c1\u062a\u0631 \u06c1\u06cc\u06ba<\/h3>\n<table>\n<thead>\n<tr>\n<th\/>\n<th>API \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u067e\u0631\u0627\u06a9\u0633\u06cc<\/th>\n<th>\u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 URL<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u0627\u06cc\u067e \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0628\u0627\u0626\u0679\u0633<\/td>\n<td>\u0627\u0646 \u0633\u0628 \u06a9\u06d2<\/td>\n<td>\u0635\u0641\u0631<\/td>\n<\/tr>\n<tr>\n<td>API CPU\/RAM \u0644\u0627\u06af\u062a<\/td>\n<td>\u0627\u0639\u0644\u06cc<\/td>\n<td>\u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2<\/td>\n<\/tr>\n<tr>\n<td>\u062a\u06be\u0631\u0648 \u067e\u0679 \u06a9\u06cc \u062d\u062f\u0648\u062f<\/td>\n<td>\u0622\u067e \u06a9\u0627 API<\/td>\n<td>MinIO \u0645\u06cc\u06ba NICs<\/td>\n<\/tr>\n<tr>\n<td>\u062a\u0635\u062f\u06cc\u0642 \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u06cc\u06ba\u06d4<\/td>\n<td>\u0622\u067e \u06a9\u0627 \u06a9\u0648\u0688<\/td>\n<td>\u0622\u067e \u06a9\u0627 \u06a9\u0648\u0688 (\u0627\u0628 \u0628\u06be\u06cc - \u062f\u0633\u062a\u062e\u0637 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"heading-11-step-8-get-public-urls-for-documents\">11. \u0645\u0631\u062d\u0644\u06c1 8 - \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06a9\u0627 \u0639\u0648\u0627\u0645\u06cc URL \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<p>\u0628\u0639\u0636 \u0627\u0648\u0642\u0627\u062a \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u0645\u0633\u062a\u0642\u0644\u060c \u063a\u06cc\u0631 \u062a\u0635\u062f\u06cc\u0642 \u0634\u062f\u06c1 \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u0686\u0627\u06c1\u06cc\u06d2 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u062c\u06cc\u0633\u06d2 \u06a9\u06c1 \u0639\u0648\u0627\u0645\u06cc \u067e\u0631\u0648\u0641\u0627\u0626\u0644 \u062a\u0635\u0648\u06cc\u0631\u06d4<\/p>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u06cc \u0628\u0627\u0644\u0679\u06cc \u067e\u0627\u0644\u06cc\u0633\u06cc \u06af\u0645\u0646\u0627\u0645 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u06cc \u06c1\u06d2 (<code>mc anonymous set download \u2026<\/code>)\u060c \u0639\u0648\u0627\u0645\u06cc URL \u067e\u06cc\u0679\u0631\u0646 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">https:\/\/minio-staging.domain.com\/<bucket>\/<key>\n<\/key><\/bucket><\/code><\/pre>\n<p>\u062a\u0648 <code>users\/42\/avatar.png<\/code> \u06cc\u06c1 \u0627\u0633 \u0637\u0631\u062d \u062c\u0627\u062a\u0627 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-plaintext\">https:\/\/minio-staging.domain.com\/domain-files-staging\/users\/42\/avatar.png\n<\/code><\/pre>\n<p>\u06a9\u0648\u0688 \u0645\u06cc\u06ba:<\/p>\n<pre><code class=\"language-javascript\">export function publicUrl(key) {\n  return `({process.env.S3_PUBLIC_ENDPOINT}\/){BUCKET}\/${key}`;\n}\n<\/code><\/pre>\n<p>\u06a9\u06d2 \u0644\u06cc\u06d2 <strong>\u0646\u062c\u06cc<\/strong> \u0628\u0627\u0644\u0679\u06cc\u0627\u06ba (\u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a)\u060c \u06a9\u0628\u06be\u06cc \u0628\u06be\u06cc \u0639\u0648\u0627\u0645\u06cc URLs \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba \u2014 \u06c1\u0645\u06cc\u0634\u06c1 \u067e\u0627\u0633 \u06a9\u0631\u06cc\u06ba\u06d4 <code>presignDownload(key)<\/code> \u0622\u067e \u06c1\u0631 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06cc \u0645\u0646\u0638\u0648\u0631\u06cc \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u06cc\u06a9 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0644\u0646\u06a9 \u06a9\u06cc \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-12-step-9-lock-down-cors-lifecycle-and-security\">12. \u0645\u0631\u062d\u0644\u06c1 9 - CORS\u060c \u0644\u0627\u0626\u0641 \u0633\u0627\u0626\u06cc\u06a9\u0644\u060c \u0627\u0648\u0631 \u0633\u06cc\u06a9\u0648\u0631\u0679\u06cc \u0644\u0627\u06a9 \u0688\u0627\u0624\u0646<\/h2>\n<h3 id=\"heading-121-allow-your-frontend-origins-cors\">12.1 \u0641\u0631\u0646\u0679 \u0627\u06cc\u0646\u0688 \u0627\u0648\u0631\u06cc\u062c\u0646\u0632 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u06ba (CORS)<\/h3>\n<p>\u0628\u0631\u0627\u0624\u0632\u0631 \u0627\u067e \u0644\u0648\u0688\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0622\u067e \u06a9\u06cc \u0628\u0627\u0644\u0679\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 CORS \u0642\u0648\u0627\u0646\u06cc\u0646 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u0633 JSON \u06a9\u0648 \u0628\u0630\u0631\u06cc\u0639\u06c1 \u062d\u0630\u0641 \u06a9\u0631\u06cc\u06ba: <code>mc<\/code>:<\/p>\n<pre><code class=\"language-bash\">cat > \/tmp\/cors.json <<'EOF'\n{\n  \"CORSRules\": [\n    {\n      \"AllowedOrigins\": [\n        \"https:\/\/crm-staging.domain.com\",\n        \"http:\/\/localhost:3000\"\n      ],\n      \"AllowedMethods\": [\"GET\", \"PUT\", \"POST\", \"HEAD\"],\n      \"AllowedHeaders\": [\"*\"],\n      \"ExposeHeaders\": [\"ETag\"],\n      \"MaxAgeSeconds\": 3000\n    }\n  ]\n}\nEOF\n\ndocker cp \/tmp\/cors.json minio-staging:\/tmp\/cors.json\ndocker exec -it minio-staging \n  mc cors set local\/domain-files-staging \/tmp\/cors.json\n<\/code><\/pre>\n<h3 id=\"heading-122-autodelete-old-test-files-lifecycle\">12.2 \u067e\u0631\u0627\u0646\u06cc \u0679\u06cc\u0633\u0679 \u0641\u0627\u0626\u0644\u0648\u06ba \u06a9\u0648 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0637\u0648\u0631 \u067e\u0631 \u062d\u0630\u0641 \u06a9\u0631\u0646\u0627 (\u0644\u0627\u0626\u0641 \u0633\u0627\u0626\u06cc\u06a9\u0644)<\/h3>\n<p>\u0633\u0679\u06cc\u062c\u0646\u06af \u0631\u062f\u06cc \u06a9\u0648 \u062c\u0645\u0639 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 MinIO \u06a9\u0648 30 \u062f\u0646 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u067e\u0631\u0627\u0646\u06cc \u062a\u0645\u0627\u0645 \u0627\u0634\u06cc\u0627\u0621 \u06a9\u06cc \u0645\u06cc\u0639\u0627\u062f \u062e\u062a\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06c1\u062f\u0627\u06cc\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-bash\">docker exec -it minio-staging \n  mc ilm rule add --expire-days 30 local\/domain-files-staging\n<\/code><\/pre>\n<h3 id=\"heading-123-encrypt-at-rest\">12.3 \u0622\u0631\u0627\u0645 \u0645\u06cc\u06ba \u062e\u0641\u06cc\u06c1 \u06a9\u0627\u0631\u06cc<\/h3>\n<pre><code class=\"language-bash\">docker exec -it minio-staging \n  mc encrypt set sse-s3 local\/domain-files-staging\n<\/code><\/pre>\n<h3 id=\"heading-124-hard-rules\">12.4 \u0633\u062e\u062a \u0627\u0635\u0648\u0644<\/h3>\n<ul>\n<li>\n<p><strong>\u0645\u0637\u0644\u0642\u06cc\u062a<\/strong> \u062c\u06c1\u0627\u0632 <code>MINIO_ROOT_USER=admin<\/code> \/ <code>MINIO_ROOT_PASSWORD=admin123<\/code> \u0627\u0646\u0679\u0631\u0646\u06cc\u0679 \u0633\u06d2 \u0642\u0627\u0628\u0644 \u0631\u0633\u0627\u0626\u06cc \u0633\u0631\u0648\u0631 \u062a\u06a9\u06d4 \u0637\u0627\u0642\u062a\u0648\u0631 \u0627\u0642\u062f\u0627\u0631 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0646\u06c1\u06cc\u06ba \u0627\u067e\u0646\u06d2 \u062e\u0641\u06cc\u06c1 \u0645\u06cc\u0646\u06cc\u062c\u0631 \u0645\u06cc\u06ba \u0645\u062d\u0641\u0648\u0638 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0631\u0648\u0679 \u0627\u06a9\u0627\u0624\u0646\u0679 \u0635\u0631\u0641 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2: <code>mc admin<\/code>\u0627\u0633\u06d2 \u0627\u067e\u0646\u06cc \u0627\u06cc\u067e\u0633 \u0645\u06cc\u06ba \u06a9\u0628\u06be\u06cc \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06cc\u067e \u0627\u0633\u06a9\u0648\u067e\u0688 IAM \u0635\u0627\u0631\u0641 (\u0645\u0631\u062d\u0644\u06c1 7.4) \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u0646\u0627 <strong>\u06a9\u0646\u0633\u0648\u0644<\/strong> \u0622\u0626\u06cc \u067e\u06cc \u0648\u0627\u0626\u0679 \u0644\u0633\u0679 \u06cc\u0627 \u0679\u0631\u06cc\u0641\u06a9 \u0645\u0688\u0644 \u0648\u06cc\u0626\u0631 \u06a9\u06d2 \u067e\u06cc\u0686\u06be\u06d2 \u0630\u06cc\u0644\u06cc \u0688\u0648\u0645\u06cc\u0646 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0628\u0646\u06cc\u0627\u062f\u06cc \u062a\u0635\u062f\u06cc\u0642 (\u0627\u06af\u0631 \u0648\u0627\u0642\u0639\u06cc \u0639\u0648\u0627\u0645\u06cc \u06c1\u06d2)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u067e\u0646\u06cc \u0627\u06cc\u067e \u062a\u06a9 \u0631\u0633\u0627\u0626\u06cc \u06a9\u06cc \u0686\u0627\u0628\u06cc\u0627\u06ba \u06a9\u0645 \u0627\u0632 \u06a9\u0645 \u06c1\u0631 90 \u062f\u0646 \u0645\u06cc\u06ba \u06af\u06be\u0645\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<h2 id=\"heading-13-step-10-backups-and-monitoring\">13. \u0645\u0631\u062d\u0644\u06c1 10 - \u0628\u06cc\u06a9 \u0627\u067e \u0627\u0648\u0631 \u0645\u0627\u0646\u06cc\u0679\u0631\u0646\u06af<\/h2>\n<h3 id=\"heading-131-backups-mirror-to-a-cheap-cold-bucket-weekly\">13.1 \u0628\u06cc\u06a9 \u0627\u067e: \u06c1\u0631 \u06c1\u0641\u062a\u06d2 \u0633\u0633\u062a\u06cc \u06a9\u0648\u0644\u0688 \u0628\u0627\u0644\u0679\u06cc \u06a9\u0627 \u0639\u06a9\u0633<\/h3>\n<p>\u0645\u06cc\u06ba \u0646\u06d2 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u06cc \u0633\u06cc \u06a9\u0631\u0648\u0646 \u062c\u0627\u0628 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc \u06c1\u06d2 \u062c\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06cc \u06c1\u06d2: <code>mc mirror<\/code> Backblaze B2\u060c R2\u060c \u06cc\u0627 \u06a9\u0633\u06cc \u0627\u0648\u0631 \u06a9\u0645 \u0644\u0627\u06af\u062a \u0648\u0627\u0644\u06d2 S3 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u067e\u0648\u0627\u0626\u0646\u0679 \u067e\u0631 \u062c\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2:<\/p>\n<pre><code class=\"language-bash\">mc alias set b2 https:\/\/s3.us-east-005.backblazeb2.com (B2_KEY )B2_SECRET\nmc mirror --overwrite --remove \n  staging\/domain-files-staging \n  b2\/domain-staging-backup\n<\/code><\/pre>\n<p>\u06cc\u06c1\u0627\u06ba \u062a\u06a9 \u06a9\u06c1 $6\/TB\/\u0645\u0627\u06c1 \u067e\u0631\u060c \u06cc\u06c1 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0648\u0627\u0644\u06cc\u0648\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0641\u062a \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-132-monitoring-with-prometheus\">13.2 Prometheus \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0646\u06af\u0631\u0627\u0646\u06cc \u06a9\u0631\u0646\u0627<\/h3>\n<p>MinIO Prometheus \u0645\u06cc\u0679\u0631\u06a9\u0633 \u06a9\u0648 \u0628\u0627\u06a9\u0633 \u0633\u06d2 \u0628\u0627\u06c1\u0631 \u0638\u0627\u06c1\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>\/minio\/v2\/metrics\/cluster<\/code>. \u0627\u0633 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0633\u06a9\u0631\u06cc\u067e \u06a9\u0631\u06cc\u06ba:<\/p>\n<pre><code class=\"language-yaml\">scrape_configs:\n  - job_name: minio\n    metrics_path: \/minio\/v2\/metrics\/cluster\n    scheme: https\n    static_configs:\n      - targets: [\"minio-staging.domain.com\"]\n<\/code><\/pre>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u06af\u0631\u0627\u0641\u0627\u0646\u0627 \u06c1\u06d2 \u062a\u0648 \u0627\u067e\u0646\u0627 \u0688\u06cc\u0634 \u0628\u0648\u0631\u0688 \u0622\u0626\u06cc \u0688\u06cc \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <strong>13502<\/strong> \u0627\u06cc\u06a9 \u0641\u0648\u0631\u06cc \u062c\u0627\u0626\u0632\u06c1 \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba (\u0635\u0644\u0627\u062d\u06cc\u062a\u060c \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06cc \u0634\u0631\u062d\u060c \u062a\u0627\u062e\u06cc\u0631\u060c \u063a\u0644\u0637\u06cc\u0648\u06ba \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f)\u06d4<\/p>\n<h2 id=\"heading-14-troubleshooting-cheat-sheet\">14. \u0679\u0631\u0628\u0644 \u0634\u0648\u0679\u0646\u06af \u0686\u06cc\u0679 \u0634\u06cc\u0679<\/h2>\n<table>\n<thead>\n<tr>\n<th>\u0639\u0644\u0627\u0645\u062a<\/th>\n<th>\u0645\u0645\u06a9\u0646\u06c1 \u0648\u062c\u06c1<\/th>\n<th>\u0679\u06be\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>SignatureDoesNotMatch<\/code>    \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 PUT \u067e\u0631<\/td>\n<td>\u0628\u0631\u0627\u0624\u0632\u0631 \u0646\u06d2 \u06a9\u0686\u06be \u0627\u0648\u0631 \u0628\u06be\u06cc\u062c\u0627 \u06c1\u06d2\u06d4 <code>Content-Type<\/code> \u062f\u0633\u062a\u062e\u0637 \u06a9\u06d2 \u0645\u0642\u0627\u0628\u0644\u06d2 \u0645\u06cc\u06ba<\/td>\n<td>\u0627\u0633\u06cc \u0637\u0631\u062d \u062e\u0631\u0686 \u06a9\u0631\u06cc\u06ba <code>Content-Type<\/code> PUT \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u06c1\u06cc\u0688\u0631<\/td>\n<\/tr>\n<tr>\n<td>\u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 URLs \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0644\u06cc\u06a9\u0646 \u0628\u0631\u0627\u0624\u0632\u0631 \u0645\u06cc\u06ba \u0646\u06c1\u06cc\u06ba\u06d4<\/td>\n<td><code>MINIO_SERVER_URL<\/code>    \u0686\u0648\u0646\u06a9\u06c1 \u06cc\u06c1 \u0633\u06cc\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2 \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u067e\u0631 \u062f\u0633\u062a\u062e\u0637 \u06a9\u06cc\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4 <code>minio:9000<\/code><\/td>\n<td>\u0633\u06cc\u0679 <code>MINIO_SERVER_URL=https:\/\/minio-staging.domain.com<\/code> \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba<\/td>\n<\/tr>\n<tr>\n<td><code>403 SignatureDoesNotMatch<\/code>    Cloudflare \u0633\u06d2 \u06af\u0632\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f<\/td>\n<td>Cloudflare \u06c1\u06cc\u0688\u0631 \u06a9\u0648 \u06c1\u0679\u0627\u062a\u0627\/\u062a\u0631\u0645\u06cc\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<td>\u0627\u067e\u0646\u06d2 DNS \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u06a9\u0648 \u0627\u0633 \u067e\u0631 \u0633\u06cc\u0679 \u06a9\u0631\u06cc\u06ba: <strong>\u0635\u0631\u0641 DNS<\/strong> (\u0633\u0631\u0645\u0626\u06cc \u0628\u0627\u062f\u0644)<\/td>\n<\/tr>\n<tr>\n<td><code>NoSuchBucket<\/code><\/td>\n<td>\u063a\u0644\u0637 \u0627\u06cc\u0646\u0688 \u067e\u0648\u0627\u0626\u0646\u0679 \u06cc\u0627 \u0628\u0627\u0644\u0679\u06cc \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0627\u06cc\u067e<\/td>\n<td>\u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba <code>S3_ENDPOINT<\/code> \u0627\u0648\u0631 <code>S3_BUCKET<\/code> \u0645\u0627\u062d\u0648\u0644 \u0645\u06cc\u06ba<\/td>\n<\/tr>\n<tr>\n<td>\u0628\u0631\u0627\u0624\u0632\u0631 CORS \u0639\u0645\u0644\u062f\u0631\u0622\u0645\u062f \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<td>\u0622\u067e \u06a9\u06cc \u0628\u0627\u0644\u0679\u06cc \u0645\u06cc\u06ba CORS \u06a9\u06d2 \u06a9\u0648\u0626\u06cc \u0627\u0635\u0648\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4<\/td>\n<td>\u00a712.1 \u06a9\u0627 CORS JSON \u0646\u0641\u0627\u0630<\/td>\n<\/tr>\n<tr>\n<td>\u0627\u067e \u0644\u0648\u0688 \u0686\u06be\u0648\u0679\u06cc \u0641\u0627\u0626\u0644\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 100MB \u06a9\u06d2 \u0644\u06cc\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<td>\u06a9\u0644\u0627\u0624\u0688 \u0641\u0644\u06cc\u0626\u0631 \u0641\u0631\u06cc \u067e\u0644\u0627\u0646 \u0628\u0627\u0688\u06cc \u06a9\u06cc \u062d\u062f\u0648\u062f<\/td>\n<td>Cloudflare \u0627\u062f\u0627 \u0634\u062f\u06c1 \u0645\u0646\u0635\u0648\u0628\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba \u06cc\u0627 CF \u067e\u0631\u0627\u06a9\u0633\u06cc \u06a9\u0648 \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<tr>\n<td><code>x509: certificate signed by unknown authority<\/code>    \u0622\u067e \u06a9\u06cc \u0627\u06cc\u067e \u0645\u06cc\u06ba<\/td>\n<td>\u0627\u06cc\u067e \u06a9\u0646\u0679\u06cc\u0646\u0631 Let's Encrypt \u067e\u0631 \u0628\u06be\u0631\u0648\u0633\u06c1 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<td>CA \u0628\u0646\u0688\u0644 \u0627\u067e \u0688\u06cc\u0679 (<code>apt install ca-certificates<\/code>) \u06cc\u0627 Docker \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u06d2 \u0627\u0646\u062f\u0631 HTTP \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<tr>\n<td>\u0648\u06cc\u0628 \u06a9\u0646\u0633\u0648\u0644 \u06a9\u0648 \u0631\u06cc \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627: <code>http:\/\/minio:9001\/login<\/code><\/td>\n<td><code>MINIO_BROWSER_REDIRECT_URL<\/code>    \u0686\u0644\u0627 \u06af\u06cc\u0627<\/td>\n<td>\u0627\u0633\u06d2 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba\u06d4 <code>https:\/\/minio-console-staging.domain.com<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u0645\u0641\u06cc\u062f \u062a\u0634\u062e\u06cc\u0635:<\/p>\n<pre><code class=\"language-bash\"># Check MinIO health\ncurl -I https:\/\/minio-staging.domain.com\/minio\/health\/live\n\n# List all objects in a bucket\ndocker exec -it minio-staging mc ls --recursive local\/domain-files-staging\n\n# Tail MinIO logs\ndocker compose -f docker-compose.staging.yml logs -f minio\n\n# Decode a presigned URL to see what it was signed for\necho \"<paste url=\"\">\" | tr '&' 'n'\n<\/paste><\/code><\/pre>\n<h2 id=\"heading-15-wrapping-up\">15. \u0646\u062a\u06cc\u062c\u06c1<\/h2>\n<p>\u06c1\u0645\u0627\u0631\u06d2 \u067e\u0627\u0633 \u0627\u0633 \u0648\u0642\u062a \u062c\u0648 \u0645\u0639\u0644\u0648\u0645\u0627\u062a \u06c1\u06cc\u06ba \u0648\u06c1 \u062f\u0631\u062c \u0630\u06cc\u0644 \u06c1\u06cc\u06ba:<\/p>\n<ul>\n<li>\n<p>\u0627\u06cc\u06a9 \u0645\u0641\u062a S3 \u0633\u06d2 \u0645\u0637\u0627\u0628\u0642\u062a \u0631\u06a9\u06be\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0627\u0633\u0679\u0648\u0631 \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0633\u0631\u0648\u0631 \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0622\u067e \u06a9\u06d2 \u062d\u0642\u06cc\u0642\u06cc \u0688\u0648\u0645\u06cc\u0646 \u067e\u0631 \u062d\u0642\u06cc\u0642\u06cc HTTPS (<code>https:\/\/minio-staging.domain.com<\/code>)\u060c Traefik + \u0622\u0626\u06cc\u06d2 \u0627\u0646\u06a9\u0631\u067e\u0679 \u06a9\u0627 \u0634\u06a9\u0631\u06cc\u06c1\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0633\u06a9\u0648\u067e\u0688 \u0633\u0628 \u0633\u06d2 \u06a9\u0645 \u0627\u0633\u062a\u062d\u0642\u0627\u0642 \u0648\u0627\u0644\u0627 \u0627\u06cc\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0635\u0627\u0631\u0641 \u2014 \u0631\u0648\u0679 \u06a9\u0644\u06cc\u062f \u0645\u0642\u0641\u0644 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062f\u0631\u0633\u062a \u06a9\u0648\u0688 \u06a9\u0627 \u0631\u0627\u0633\u062a\u06c1 \u0627\u0633\u0679\u06cc\u062c\u0646\u06af \u0627\u0648\u0631 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u062c\u06cc\u0633\u0627 \u06c1\u06d2\u06d4 MinIO\/R2\/Hetzner\/AWS S3 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0633\u0648\u0626\u0686 \u06a9\u0631\u0646\u0627 env \u0641\u0627\u0626\u0644 \u0645\u06cc\u06ba \u0686\u0627\u0631 \u0645\u062a\u063a\u06cc\u0631\u0627\u062a \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u06a9 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 PUT URL \u062c\u0648 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u0648 API \u06a9\u0648 \u0646\u0638\u0631\u0627\u0646\u062f\u0627\u0632 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u0645\u06cc\u06ba \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 GET \u06cc\u0648 \u0622\u0631 \u0627\u06cc\u0644 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u0630\u0627\u062a\u06cc \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u06a9\u06cc \u0639\u0645\u0631 \u06a9\u0645 \u06c1\u06d2 \u0627\u0648\u0631 \u062a\u0648\u062b\u06cc\u0642 \u0645\u062d\u062f\u0648\u062f \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u06a9 \u0644\u0627\u0626\u0641 \u0633\u0627\u0626\u06cc\u06a9\u0644 \u0627\u0635\u0648\u0644 \u062c\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u067e\u0631\u0627\u0646\u06cc \u0679\u06cc\u0633\u0679 \u0641\u0627\u0626\u0644\u0648\u06ba \u06a9\u0648 \u0646\u06cc\u0648\u06a9\u0644\u06cc\u0679\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0648\u0644\u0688 \u0628\u06cc\u06a9 \u0627\u067e \u0628\u0627\u0644\u0679\u06cc\u0648\u06ba \u06a9\u06cc \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u06c1\u0641\u062a\u06c1 \u0648\u0627\u0631 \u0639\u06a9\u0633 \u0628\u0646\u062f\u06cc\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u06c1\u0645 SLAs \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0645\u0646\u0638\u0645 \u0627\u0633\u0679\u0648\u0631\u06cc\u062c \u067e\u0631 \u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u062c\u0627\u0631\u06cc \u06c1\u06d2\u06d4 \u0633\u0679\u06cc\u062c\u0646\u06af \u06a9\u06d2 \u0627\u062e\u0631\u0627\u062c\u0627\u062a \u0627\u0628 \u0628\u0627\u0644\u06a9\u0644 \u062f\u0631\u0633\u062a \u06c1\u06cc\u06ba\u06d4 <strong>$0 \u0641\u06cc \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u062f\u06c1 \u06af\u06cc\u06af\u0627 \u0628\u0627\u0626\u0679 \u0641\u06cc \u0645\u06c1\u06cc\u0646\u06c1<\/strong> - \u0627\u0648\u0631 \u06c1\u0645 \u0622\u062e\u0631 \u06a9\u0627\u0631 QA \u06a9\u0648 \u06cc\u06c1 \u0628\u062a\u0627\u0646\u0627 \u0628\u0646\u062f \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \"\u062c\u0628 \u0622\u067e \u06a9\u0627\u0645 \u06a9\u0631 \u0644\u06cc\u06ba \u062a\u0648 \u0679\u06cc\u0633\u0679 \u0641\u0627\u0626\u0644\u0648\u06ba \u06a9\u0648 \u062d\u0630\u0641 \u06a9\u0631 \u062f\u06cc\u06ba\u06d4\"<\/p>\n<h3 id=\"heading-further-reading\">\u0627\u0636\u0627\u0641\u06cc \u0648\u0633\u0627\u0626\u0644<\/h3>\n<p>\u0627\u06af\u0631 \u06cc\u06c1 \u06af\u0627\u0626\u06cc\u0688 \u0622\u067e \u06a9\u06cc \u0679\u06cc\u0645 \u06a9\u0648 \u0686\u0646\u062f \u0688\u0627\u0644\u0631 \u0628\u0686\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633\u06d2 \u062f\u0648\u0633\u0631\u06cc \u0679\u06cc\u0645\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0634\u06cc\u0626\u0631 \u06a9\u0631\u06cc\u06ba \u062c\u0648 \u0627\u0628 \u0628\u06be\u06cc $90\/\u0645\u0627\u06c1 \u06a9\u06cc S3 \u0628\u0627\u0644\u0679\u06cc \u0645\u06cc\u06ba \u0679\u06cc\u0633\u0679 \u067e\u06cc \u0688\u06cc \u0627\u06cc\u0641 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631 \u0631\u06c1\u06cc \u06c1\u06cc\u06ba\u06d4 \u0645\u0628\u0627\u0631\u06a9 \u0634\u067e\u0646\u06af.<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u06cc\u06c1 \u0645\u0636\u0645\u0648\u0646 HTTPS\u060c \u06a9\u0633\u0679\u0645 \u0688\u0648\u0645\u06cc\u0646\u0632\u060c \u0627\u0648\u0631 \u0635\u0631\u0641 Docker Compose \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062f\u0633\u062a\u062e\u0637 \u0634\u062f\u06c1 \u0627\u067e \u0644\u0648\u0688\/\u0688\u0627\u0624\u0646 \u0644\u0648\u0688 URLs \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 Traefik \u06a9\u06d2 \u067e\u06cc\u0686\u06be\u06d2 MinIO \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0645\u06a9\u0645\u0644 \u06a9\u0627\u067e\u06cc \u067e\u06cc\u0633\u0679 \u06af\u0627\u0626\u06cc\u0688 \u06c1\u06d2\u06d4 \u0622\u067e \u06a9\u06cc \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u0645\u0646\u0638\u0645 S3\/Cloudflare R2\/Hetzner \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0633\u0679\u0648\u0631\u06cc\u062c \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u06d2 \u06af\u06cc\u060c \u062c\u0628\u06a9\u06c1 \u062a\u0645\u0627\u0645 \u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":24795,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-24794","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/24794","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/comments?post=24794"}],"version-history":[{"count":1,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/24794\/revisions"}],"predecessor-version":[{"id":24796,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/24794\/revisions\/24796"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media\/24795"}],"wp:attachment":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media?parent=24794"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/categories?post=24794"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/tags?post=24794"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}