اسٹیجنگ سرور پر MinIO کا استعمال کرتے ہوئے S3 کے موافق آبجیکٹ اسٹوریج کی خود میزبانی کیسے کریں (اور ماہانہ سینکڑوں ڈالر بچائیں)

یہ مضمون HTTPS، کسٹم ڈومینز، اور صرف Docker Compose کا استعمال کرتے ہوئے پہلے سے دستخط شدہ اپ لوڈ/ڈاؤن لوڈ URLs کا استعمال کرتے ہوئے Traefik کے پیچھے MinIO چلانے کے لیے ایک مکمل کاپی پیسٹ گائیڈ ہے۔

آپ کی پروڈکشن منظم S3/Cloudflare R2/Hetzner آبجیکٹ سٹوریج کا استعمال جاری رکھے گی، جبکہ تمام مرحلہ وار اپ لوڈز، ڈاؤن لوڈز اور پہلے سے دستخط شدہ URLs کو آپ کے پر اسٹور کیا جائے گا۔ اپنے سرور مفت فراہم کیا جاتا ہے۔

انڈیکس

1. سٹیجنگ کو خود میزبان آبجیکٹ اسٹوریج کی ضرورت کیوں ہے؟

اگر آپ کی ایپ دستاویزات (PDFs، پروفائل پکچرز، ایپلیکیشن ہسٹری، ریکارڈنگز) پر کارروائی کرتی ہے، تو آپ کی QA ٹیم کے اپ لوڈ کردہ ہر ٹیسٹ کے حقیقی اخراجات AWS S3، Cloudflare R2، یا Hetzner Object Storage میں ہوں گے۔ اگرچہ فی فائل کی قیمت معمولی ہے، اسٹیجنگ آپ کو اجازت دیتی ہے:

  • ہزاروں ڈمی فائلوں کو اپ لوڈ کرتے ہوئے خودکار اینڈ ٹو اینڈ ٹیسٹ چلائیں،

  • ڈیٹا بیس کو رات کے وقت دوبارہ ترتیب دیں (یتیم اشیاء کو پیچھے چھوڑ کر)۔

  • ڈویلپر اسی فائل کو دوبارہ اپ لوڈ کر کے ٹوٹے ہوئے کوڈ کے ساتھ تجربہ کر سکتے ہیں۔

  • ہم مہینوں کے ٹیسٹ ڈیٹا رکھتے ہیں جسے کوئی بھی کبھی حذف نہیں کرتا ہے۔

پیداواری عمل میں یہ اخراجات جائز ہیں۔ منظم اسٹوریج نقل، دستیابی، اور کسی اور کا پیجر فراہم کرتا ہے۔ تیاری میں یہ اخراجات خالص فضلہ ہیں۔

MiniIO ایک مفت اور اوپن سورس S3 ہم آہنگ آبجیکٹ سرور۔ وہی API، وہی SDK، وہی پہلے سے دستخط شدہ URL، وہی mc/aws s3 CLI – آپ کے اپنے VPS پر چلتا ہے اور اس کی قیمت $0 فی گیگا بائٹ ہے۔ اگر آپ MinIO کو اپنی اسٹیجنگ ایپ کی طرف اور S3/R2 کو اپنی پروڈکشن ایپ کی طرف اشارہ کرتے ہیں، تو صرف وہی چیزیں تبدیل ہوتی ہیں جو ماحولیاتی متغیرات ہیں۔

نتیجہ: دونوں ماحول میں ایک ہی کوڈ کا راستہ، اسٹیج کرتے وقت اسٹوریج کی کوئی قیمت نہیں، اور اگر آپ کا کلاؤڈ فراہم کنندہ باہر چلا جاتا ہے تو اچھا فال بیک۔

2. فن تعمیر: پیداوار اور اسٹیجنگ

حقیقی دنیا کی ایپلی کیشنز میں، آپ عام طور پر نہیں چاہتے ہیں کہ آپ کی ترقی یا اسٹیجنگ ماحول کو براہ راست پروڈکشن اسٹوریج میں لکھا جائے۔

عام اور سرمایہ کاری مؤثر سیٹ اپ میں شامل ہیں:

اچھی بات یہ ہے کہ آپ کو اپنا ایپلیکیشن کوڈ تبدیل کرنے کی ضرورت نہیں ہے۔

جب تک دونوں سروسز S3 کے ساتھ مطابقت رکھتی ہیں، ایک ہی SDK اور اپ لوڈ منطق کہیں بھی کام کرے گی۔ صرف ماحولیاتی متغیرات مختلف ہیں۔

اعلی سطحی فن تعمیر

اوپر دیا گیا خاکہ دکھاتا ہے کہ تعیناتی کے ماحول کے لحاظ سے ایک ہی ایپلیکیشن مختلف سٹوریج فراہم کنندگان کے ساتھ کیسے بات چیت کرتی ہے۔

پر پیداواری ماحولاپ لوڈز کو ایک منظم آبجیکٹ اسٹوریج سروس جیسے AWS S3، Cloudflare R2، یا Hetzner Object Storage میں محفوظ کیا جاتا ہے۔ یہ خدمات پائیداری، اسکیل ایبلٹی، بیک اپ اور بنیادی ڈھانچے کا انتظام سنبھالتی ہیں۔

پر سٹیجنگ ماحولاپ لوڈز کو آپ کے VPS پر Docker کے اندر چلنے والے خود میزبان MinIO مثال کے لیے روٹ کیا جاتا ہے۔ MinIO لاگت کو کم رکھتے ہوئے پروڈکشن اسٹوریج کی طرح کام کرنے کے لیے S3 API کو لاگو کرتا ہے۔

دونوں سٹوریج سسٹم S3 کے موافق ہیں، لہذا آپ کی ایپلیکیشن تمام ماحول میں ایک ہی اپ لوڈ منطق کا استعمال کرتی ہے۔ فرق صرف ماحول کے متغیرات کے ذریعے فراہم کردہ ترتیب ہے۔

یہ فن تعمیر کیوں مفید ہے۔

یہ ترتیب فراہم کرتی ہے:

  • سستی سٹیجنگ ماحول

  • پیداوار کی طرح کی جانچ

  • زیرو اسٹوریج وینڈر لاک ان

  • ایپلیکیشن کوڈ کو دوبارہ لکھے بغیر فراہم کنندگان کو تبدیل کرنے کی اہلیت

دونوں ماحول S3 پروٹوکول کا استعمال کرتے ہیں، لہذا اپ لوڈ کی منطق ایک جیسی رہتی ہے۔

ماحولیاتی متغیر کی مثال

ایپلیکیشن صرف درج ذیل ماحولیاتی متغیرات کو پڑھتی ہے:

S3_ENDPOINT=
S3_REGION=
S3_ACCESS_KEY=
S3_SECRET_KEY=
S3_BUCKET=

اقدار کو تبدیل کرنے سے، وہی ایپلیکیشن اب فائل کو مختلف بیک اینڈ پر اپ لوڈ کرے گی۔

پروڈکشن اسٹوریج کی مثال

پروڈکشن میں، آپ عام طور پر درج ذیل مینیجڈ آبجیکٹ اسٹوریج فراہم کرنے والے استعمال کرتے ہیں:

  • AWS S3

  • Cloudflare R2

  • ہیٹزنر آبجیکٹ اسٹوریج

ہاں:

S3_ENDPOINT=https://.r2.cloudflarestorage.com

فوائد یہ ہیں کہ یہ انتہائی قابل توسیع ہے، عالمی سطح پر دستیاب ہے، پائیدار ہے، بیک اپ کا انتظام کرتا ہے، اور بنیادی ڈھانچے کی دیکھ بھال نہیں ہے۔

سٹیجنگ ماحول کی مثال

سٹیجنگ کے لیے، ہلکے وزن کے خود میزبان MinIO کنٹینرز اکثر کافی ہوتے ہیں۔

Next.js App
     ↓
MinIO Container (inside Docker on VPS)

مثال ڈومین:

یہ آپ کو اجازت دیتا ہے:

3. شرطیں

آپ کو ضرورت ہو گی:

  • Linux VPS (Hetzner، DigitalOcean، Contabo، OVH — عوامی IP کے ساتھ کچھ بھی)۔

  • اس آئی پی کی طرف اشارہ کرنے والے دو A ریکارڈ (ہم انہیں اگلی رجسٹر کریں گے)۔

  • ڈوکر + ڈوکر کمپوز v2۔

  • Traefik v2 جس میں Let’s Encrypt ترتیب دیا گیا ہے (تمام ریورس پراکسی کام کرتی ہیں – نیچے دیے گئے لیبل Traefik کی خصوصیات ہیں)۔

  • کھلی بندرگاہ 80 اور 443 Let’s Encrypt + HTTPS کے لیے فائر وال میں۔

  • MinIO ڈیٹا والیوم شروع کرنے کے لیے 10 GB تک مفت ڈسک۔

اگر ڈوکر انسٹال نہیں ہے:

curl -fsSL https://get.docker.com | sh
sudo apt-get install -y docker-compose-plugin
docker --version && docker compose version

4. مرحلہ 1 – DNS: اپنے ڈومین کو اسٹیجنگ سرور کی طرف اشارہ کریں۔

آپ کے DNS فراہم کنندہ سے دو (Cloudflare، Route 53، Namecheap، وغیرہ) ایک ریکارڈ اسٹیجنگ سرور کے عوامی IP کی طرف اشارہ کرتا ہے۔

minio-staging.domain.com           A    203.0.113.45
minio-console-staging.domain.com   A    203.0.113.45

اگر آپ Cloudflare استعمال کر رہے ہیں، تو اپنی پراکسی اسٹیٹس کو اس پر سیٹ کریں: صرف DNS (سرمئی بادل) minio-staging.*. Cloudflare کا مفت منصوبہ اپ لوڈز کو 100MB تک محدود کرتا ہے اور یہ نہیں چاہتا کہ آپ S3 دستخطی ہیڈر کو ہٹا دیں۔ اگر آپ اپنے WAF کو سامنے لانا چاہتے ہیں، تو آپ اپنے کنسول کے ذیلی ڈومین کو پراکسیڈ رکھ سکتے ہیں۔

براہ کرم ایک لمحہ انتظار کریں اور درج ذیل کو چیک کریں:

dig +short minio-staging.domain.com
# 203.0.113.45

5. مرحلہ 2 – ڈوکر کمپوز کے ساتھ MinIO چلائیں۔

آپ اس سروس کو سٹیجنگ تخلیق فائل میں استعمال کر سکتے ہیں (docker-compose.staging.yml)۔ MinIO صرف ایک کنٹینر ہے۔ ڈسک کو ڈوکر والیوم کے طور پر نصب کیا جاتا ہے، لہذا اپ گریڈ کے بعد آپ کا ڈیٹا برقرار رہتا ہے۔

# docker-compose.staging.yml
networks:
  proxy:
    external: true
    name: proxy
  internal:
    name: internal

volumes:
  minio-data:

services:
  minio:
    image: minio/minio:latest
    container_name: minio-staging
    restart: unless-stopped
    environment:
      - MINIO_ROOT_USER=${MINIO_ROOT_USER:-admin}
      - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-change-me-please}
      # Tell MinIO which public domain to sign URLs with
      - MINIO_SERVER_URL=https://minio-staging.domain.com
      - MINIO_BROWSER_REDIRECT_URL=https://minio-console-staging.domain.com
    command: server /data --console-address ":9001"
    volumes:
      - minio-data:/data
    networks:
      - proxy
      - internal
    ports:
      - "9000:9000"  # S3 API
      - "9001:9001"  # Web console
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 30s

دو باتیں قابل توجہ ہیں۔

  • MINIO_SERVER_URL یہ خفیہ چٹنی ہے۔ اس کے بغیر، MinIO داخلی میزبان نام استعمال نہیں کرے گا (http://minio:9000)، توثیق اس وقت ناکام ہو جاتی ہے جب براؤزر عوامی ڈومین سے ٹکرا جاتا ہے۔ اسے بالکل وہی HTTPS URL پر سیٹ کریں جسے آپ کے کلائنٹ استعمال کریں گے۔

  • MINIO_BROWSER_REDIRECT_URL ویب کنسول بھی ایسا ہی کرتا ہے (لاگ ان ری ڈائریکٹس، OIDC کال بیکس وغیرہ)۔

براہ کرم لائیں:

docker compose -f docker-compose.staging.yml up -d minio
docker compose -f docker-compose.staging.yml logs -f minio

آپ کو دیکھنا چاہئے API: http://... اور Console: http://... سموچ

6. مرحلہ 3 – Traefik کا استعمال کرتے ہوئے HTTPS پر MinIO کو بے نقاب کریں۔

ہم بندرگاہوں کو بے نقاب نہیں کرتے ہیں۔ 9000/9001 براہ راست دنیا کے لیے — Traefik ہمارے لیے مفت Let’s Encrypt سرٹیفکیٹس کے ساتھ TLS کو ختم کر کے ایسا کرتا ہے۔

مندرجہ ذیل لیبل minio سروس:

    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=proxy"

      # ---- S3 API (port 9000) ----
      - "traefik.http.routers.minio-staging.rule=Host(`minio-staging.domain.com`)"
      - "traefik.http.routers.minio-staging.entrypoints=websecure"
      - "traefik.http.routers.minio-staging.tls.certresolver=letsencrypt"
      - "traefik.http.routers.minio-staging.service=minio-staging"
      - "traefik.http.services.minio-staging.loadbalancer.server.port=9000"

      # ---- Web Console (port 9001) ----
      - "traefik.http.routers.minio-console-staging.rule=Host(`minio-console-staging.domain.com`)"
      - "traefik.http.routers.minio-console-staging.entrypoints=websecure"
      - "traefik.http.routers.minio-console-staging.tls.certresolver=letsencrypt"
      - "traefik.http.routers.minio-console-staging.service=minio-console-staging"
      - "traefik.http.services.minio-console-staging.loadbalancer.server.port=9001"

آپ بھی entrypoint کے لیے :443 اور certificatesresolver نامزد letsencrypt. کم از کم Traefik ترتیب مندرجہ ذیل ہے (traefik.staging.yml):

api:
  dashboard: true

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

certificatesResolvers:
  letsencrypt:
    acme:
      httpChallenge:
        entryPoint: web
      email: admin@domain.com
      storage: /etc/traefik/acme.json

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: proxy

دوبارہ شروع کریں اور سرٹیفکیٹ جاری ہوتے ہی دیکھیں۔

docker compose -f docker-compose.staging.yml up -d
docker compose -f docker-compose.staging.yml logs -f traefik | grep -i acme

اپنے لیپ ٹاپ پر اسٹیٹس چیک کریں:

curl -I https://minio-staging.domain.com/minio/health/live
# HTTP/2 200

اب آپ اگلی بار لاگ ان کر سکتے ہیں۔ ویب کنسول کو https://minio-console-staging.domain.com کے ساتھ admin / change-me-please.

اہم اپ لوڈ سائزنگ: اگر آپ Traefik کے سامنے Cloudflare یا NGINX کے پیچھے ہیں، تو درخواست کی باڈی کی حد میں اضافہ کریں۔ Traefik کی خود کوئی ڈیفالٹ حد نہیں ہے، لیکن Cloudflare کا مفت منصوبہ 100MB سے زیادہ کسی بھی چیز کو مسترد کرتا ہے۔ سیلف ہوسٹڈ ایج پراکسی کے لیے، درج ذیل سیٹ کریں: client_max_body_size 0; (NGINX) یا اس کے مساوی۔

7. مرحلہ 4 – بالٹی اور رسائی کلید بنائیں

S3 استعمال کرنے والی کوئی بھی چیز MinIO سے بات کر سکتی ہے۔ سب سے آسان ٹول ہے۔ mc (آفیشل MinIO کلائنٹ)، اسی تصویر کے اندر فراہم کردہ۔

7.1 MC کو سرور سے جوڑیں۔

docker exec -it minio-staging 
  mc alias set local http://localhost:9000 admin change-me-please

7.2 بالٹی بنائیں

docker exec -it minio-staging mc mb local/domain-files-staging

7.3 بالٹی پالیسی منتخب کریں۔

آپ کے پاس تین انتخاب ہیں، لہذا آپ نے جو محفوظ کیا ہے اس کی بنیاد پر انتخاب کریں۔

پالیسی میں اسے کب استعمال کروں؟
private (بنیادی) طالب علم کی نقلیں، معاہدے، اندرونی دستاویزات، کچھ بھی حساس۔ صرف پہلے سے دستخط شدہ URLs سے پڑھتا ہے۔
download کھلا پڑھنا، غیر فہرست۔ اوتار جیسے CDN طرز کے اثاثوں کے لیے بہترین۔
public کوئی بھی پڑھ سکتا ہے اور فہرست بنا سکتا ہے۔ صرف حقیقی عوامی مواد کے لیے استعمال کریں۔

ایک ترتیب دیں:

# Private (recommended for documents)
docker exec -it minio-staging 
  mc anonymous set none local/domain-files-staging

# OR public read for static assets only:
docker exec -it minio-staging 
  mc anonymous set download local/domain-files-staging

7.4 سرشار ایپ صارفین بنائیں (روٹ کلید استعمال نہ کریں!)

کہ admin آپ کا اکاؤنٹ ہر چیز سے صاف کیا جا سکتا ہے۔ اپنی ایپ کے لیے کم سے کم مراعات یافتہ صارف بنائیں۔

docker exec -it minio-staging mc admin user add local 
  domain-app a-long-random-secret-key

# Attach the built-in read/write policy, scoped to one bucket via JSON:
cat > /tmp/policy.json <<'EOF'
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:*"],
      "Resource": [
        "arn:aws:s3:::domain-files-staging",
        "arn:aws:s3:::domain-files-staging/*"
      ]
    }
  ]
}
EOF

docker cp /tmp/policy.json minio-staging:/tmp/policy.json
docker exec -it minio-staging 
  mc admin policy create local domain-rw /tmp/policy.json
docker exec -it minio-staging 
  mc admin policy attach local domain-rw --user domain-app

ان دو قدروں کو محفوظ کریں۔ S3_ACCESS_KEY اور S3_SECRET_KEY.

8. مرحلہ 5 - صرف تیاری کے مرحلے میں MinIO استعمال کرنے کے لیے ایپ کو کنفیگر کریں۔

"اسٹیجنگ میں MinIO، پیداوار میں حقیقی S3" کا راز ایک ہی S3 کلائنٹ اپنے کوڈ میں صرف env vars کو تبدیل کریں۔

آپ کا staging.env (اسٹیجنگ تخلیق اسٹیک سے بھری ہوئی):

# ---- Staging: self-hosted MinIO ----
STORAGE_ENABLED=true
S3_ENDPOINT=https://minio-staging.domain.com
S3_PUBLIC_ENDPOINT=https://minio-staging.domain.com
S3_BUCKET=domain-files-staging
S3_ACCESS_KEY=domain-app
S3_SECRET_KEY=a-long-random-secret-key
S3_REGION=us-east-1
S3_FORCE_PATH_STYLE=true

آپ کا production.env:

# ---- Production: Cloudflare R2 ----
STORAGE_ENABLED=true
S3_ENDPOINT=https://.r2.cloudflarestorage.com
S3_PUBLIC_ENDPOINT=https://files.domain.com
S3_BUCKET=domain-files
S3_ACCESS_KEY=
S3_SECRET_KEY=
S3_REGION=auto
S3_FORCE_PATH_STYLE=true

S3_FORCE_PATH_STYLE=true MinIO سب کے لیے اہم ہے۔ اور R2/Hetzner۔ اس کے بغیر، SDK کوشش کرے گا: https://bucket.minio-staging.domain.com (ورچوئل ہوسٹ اسٹائل)، حل نہیں ہوتا ہے۔

اب آپ کے ایپلیکیشن کوڈ میں (AWS SDK v3 کا استعمال کرتے ہوئے Node.js مثال):

// src/lib/s3.js
import { S3Client } from "@aws-sdk/client-s3";

export const s3 = new S3Client({
  endpoint: process.env.S3_ENDPOINT,
  region: process.env.S3_REGION,
  credentials: {
    accessKeyId: process.env.S3_ACCESS_KEY,
    secretAccessKey: process.env.S3_SECRET_KEY,
  },
  forcePathStyle: process.env.S3_FORCE_PATH_STYLE === "true",
});

export const BUCKET = process.env.S3_BUCKET;
export const PUBLIC_ENDPOINT = process.env.S3_PUBLIC_ENDPOINT;

ایک ہی s3 آپ کی مثال اب منائیو کے ساتھ سٹیجنگ میں اور پروڈکشن میں R2 کے ساتھ بغیر کسی کوڈ کی تبدیلی کے بات چیت کرتی ہے۔

9. مرحلہ 6 - فائلیں اپ لوڈ کریں (3 طریقے)

9.1 سرور پر (قابل اعتماد بیک اینڈز کے لیے بہترین)

import { PutObjectCommand } from "@aws-sdk/client-s3";
import { s3, BUCKET } from "./lib/s3.js";
import { readFile } from "node:fs/promises";

export async function uploadDocument(localPath, key, contentType) {
  const Body = await readFile(localPath);
  await s3.send(new PutObjectCommand({
    Bucket: BUCKET,
    Key: key,
    Body,
    ContentType: contentType,
    // Optional: per-object metadata, useful for audits
    Metadata: { uploadedBy: "system", env: process.env.NODE_ENV },
  }));
  return key;
}

9.2 mc CLI استعمال کرنا (ایک بار اپ لوڈ/مائیگریشن کے لیے موزوں)

mc alias set staging https://minio-staging.domain.com domain-app a-long-random-secret-key
mc cp ./report.pdf staging/domain-files-staging/reports/2026/report.pdf
mc ls staging/domain-files-staging --recursive

9.3 براہ راست اپنے براؤزر سے پہلے سے دستخط شدہ PUT URL کے ذریعے

صارف کے اپ لوڈز کے لیے تجویز کردہ پیٹرن یہ ہے: فائل آپ کے براؤزر میں MinIO پر جاتی ہے۔ صفر یہ وہ بائٹس ہیں جو API سرور کو مارتے ہیں۔

ہم اگلی بار اس پر مزید تفصیل سے بات کریں گے۔

10. مرحلہ 7 - پہلے سے دستخط شدہ URLs بنائیں (PUT اور GET)

کوئی راستہ نہیں پہلے سے دستخط شدہ URL ایک سادہ HTTPS URL جس میں استفسار کے اسٹرنگ میں ایک وقت محدود دستخط ہے۔ URL کے ساتھ کوئی بھی شخص اگلے N منٹ کے لیے بالکل دستخط شدہ آپریشن کر سکتا ہے (اس چیز کو ڈالیں یا اس چیز کو حاصل کریں) اور کچھ نہیں۔

یہ وہی ہے جو "صارف کو براہ راست اسٹوریج پر اپ لوڈ کرتا ہے" کو محفوظ بناتا ہے۔

10.1 پہلے سے دستخط شدہ PUT (اپ لوڈ کے لیے)

// src/lib/presign.js
import { PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { s3, BUCKET } from "./s3.js";
import { randomUUID } from "node:crypto";

export async function presignUpload({ filename, contentType, userId }) {
  const key = `users/({userId}/){randomUUID()}-${filename}`;
  const cmd = new PutObjectCommand({
    Bucket: BUCKET,
    Key: key,
    ContentType: contentType,
  });
  const uploadUrl = await getSignedUrl(s3, cmd, { expiresIn: 60 * 5 }); // 5 min
  return { uploadUrl, key };
}

ہمارے API سے جڑیں۔

// POST /api/uploads/presign
app.post("/api/uploads/presign", requireAuth, async (req, res) => {
  const { filename, contentType } = req.body;
  const result = await presignUpload({
    filename,
    contentType,
    userId: req.user.id,
  });
  res.json(result); // { uploadUrl, key }
});

براؤزر براہ راست MinIO پر اپ لوڈ کرتے ہیں۔

// In your frontend
async function uploadFile(file) {
  const { uploadUrl, key } = await fetch("/api/uploads/presign", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ filename: file.name, contentType: file.type }),
  }).then(r => r.json());

  await fetch(uploadUrl, {
    method: "PUT",
    headers: { "Content-Type": file.type },
    body: file,
  });

  // Persist `key` in your DB so you can retrieve it later
  await fetch("/api/documents", {
    method: "POST",
    body: JSON.stringify({ key, originalName: file.name }),
  });
}

کہ Content-Type PUT کے دوران بھیجتے وقت ملنا چاہئے بصورت دیگر MinIO درخواست کو مسترد کر دے گا۔ SignatureDoesNotMatch. یہ پہلی بار سب کو پکڑتا ہے۔

10.2 پہلے سے دستخط شدہ GET (ڈاؤن لوڈ کے لیے)

حالانکہ میں بھی یہی سوچتا ہوں۔ GetObjectCommand:

export async function presignDownload(key, expiresIn = 60 * 10) {
  const cmd = new GetObjectCommand({ Bucket: BUCKET, Key: key });
  return getSignedUrl(s3, cmd, { expiresIn });
}

عام "دستاویز دیکھیں" کے اختتامی نکات:

app.get("/api/documents/:id/url", requireAuth, async (req, res) => {
  const doc = await db.documents.findById(req.params.id);
  if (!doc || !canUserSee(req.user, doc)) return res.sendStatus(403);
  const url = await presignDownload(doc.key, 600);
  res.json({ url });
});

فرنٹ اینڈ اس URL کو کھولتا ہے۔ فائلوں کو MinIO سے براہ راست صارف تک پہنچایا جاتا ہے۔

10.3 پہلے سے دستخط شدہ URL کیوں "پراکسی بذریعہ API" سے بہتر ہیں

API کے ذریعے پراکسی پہلے سے دستخط شدہ URL
ایپ کے ذریعے بائٹس ان سب کے صفر
API CPU/RAM لاگت اعلی موجود نہیں ہے
تھرو پٹ کی حدود آپ کا API MinIO میں NICs
تصدیق کی تصدیق کریں۔ آپ کا کوڈ آپ کا کوڈ (اب بھی - دستخط کرنے سے پہلے چیک کریں)

11. مرحلہ 8 - دستاویز کا عوامی URL حاصل کریں۔

بعض اوقات آپ کو ایک مستقل، غیر تصدیق شدہ یو آر ایل چاہیے ہو سکتا ہے، جیسے کہ عوامی پروفائل تصویر۔

اگر آپ کی بالٹی پالیسی گمنام پڑھنے کی اجازت دیتی ہے (mc anonymous set download …)، عوامی URL پیٹرن ہے:

https://minio-staging.domain.com//

تو users/42/avatar.png یہ اس طرح جاتا ہے:

https://minio-staging.domain.com/domain-files-staging/users/42/avatar.png

کوڈ میں:

export function publicUrl(key) {
  return `({process.env.S3_PUBLIC_ENDPOINT}/){BUCKET}/${key}`;
}

کے لیے نجی بالٹیاں (زیادہ تر دستاویزات)، کبھی بھی عوامی URLs کا استعمال نہ کریں — ہمیشہ پاس کریں۔ presignDownload(key) آپ ہر درخواست کی منظوری کو دوبارہ چیک کر سکتے ہیں اور لنک کی میعاد ختم کر سکتے ہیں۔

12. مرحلہ 9 - CORS، لائف سائیکل، اور سیکورٹی لاک ڈاؤن

12.1 فرنٹ اینڈ اوریجنز کی اجازت دیں (CORS)

براؤزر اپ لوڈز کے لیے آپ کی بالٹی کے لیے CORS قوانین کی ضرورت ہوتی ہے۔ اس JSON کو بذریعہ حذف کریں: mc:

cat > /tmp/cors.json <<'EOF'
{
  "CORSRules": [
    {
      "AllowedOrigins": [
        "https://crm-staging.domain.com",
        "http://localhost:3000"
      ],
      "AllowedMethods": ["GET", "PUT", "POST", "HEAD"],
      "AllowedHeaders": ["*"],
      "ExposeHeaders": ["ETag"],
      "MaxAgeSeconds": 3000
    }
  ]
}
EOF

docker cp /tmp/cors.json minio-staging:/tmp/cors.json
docker exec -it minio-staging 
  mc cors set local/domain-files-staging /tmp/cors.json

12.2 پرانی ٹیسٹ فائلوں کو خودکار طور پر حذف کرنا (لائف سائیکل)

سٹیجنگ ردی کو جمع کرتا ہے۔ MinIO کو 30 دن سے زیادہ پرانی تمام اشیاء کی میعاد ختم کرنے کی ہدایت کرتا ہے۔

docker exec -it minio-staging 
  mc ilm rule add --expire-days 30 local/domain-files-staging

12.3 آرام میں خفیہ کاری

docker exec -it minio-staging 
  mc encrypt set sse-s3 local/domain-files-staging

12.4 سخت اصول

  • مطلقیت جہاز MINIO_ROOT_USER=admin / MINIO_ROOT_PASSWORD=admin123 انٹرنیٹ سے قابل رسائی سرور تک۔ طاقتور اقدار پیدا کریں اور انہیں اپنے خفیہ مینیجر میں محفوظ کریں۔

  • روٹ اکاؤنٹ صرف درج ذیل صارفین کو استعمال کرنا چاہیے: mc adminاسے اپنی ایپس میں کبھی استعمال نہ کریں۔ ایپ اسکوپڈ IAM صارف (مرحلہ 7.4) استعمال کرتی ہے۔

  • برقرار رکھنا کنسول آئی پی وائٹ لسٹ یا ٹریفک مڈل ویئر کے پیچھے ذیلی ڈومین کے ذریعے بنیادی تصدیق (اگر واقعی عوامی ہے)۔

  • اپنی ایپ تک رسائی کی چابیاں کم از کم ہر 90 دن میں گھمائیں۔

13. مرحلہ 10 - بیک اپ اور مانیٹرنگ

13.1 بیک اپ: ہر ہفتے سستی کولڈ بالٹی کا عکس

میں نے ایک چھوٹی سی کرون جاب ترتیب دی ہے جو استعمال کرتی ہے: mc mirror Backblaze B2، R2، یا کسی اور کم لاگت والے S3 اختتامی پوائنٹ پر جانے کے لیے:

mc alias set b2 https://s3.us-east-005.backblazeb2.com (B2_KEY )B2_SECRET
mc mirror --overwrite --remove 
  staging/domain-files-staging 
  b2/domain-staging-backup

یہاں تک کہ $6/TB/ماہ پر، یہ بنیادی طور پر اسٹیجنگ والیوم کے لیے مفت ہے۔

13.2 Prometheus کا استعمال کرتے ہوئے نگرانی کرنا

MinIO Prometheus میٹرکس کو باکس سے باہر ظاہر کرتا ہے۔ /minio/v2/metrics/cluster. اس کا استعمال کرتے ہوئے سکریپ کریں:

scrape_configs:
  - job_name: minio
    metrics_path: /minio/v2/metrics/cluster
    scheme: https
    static_configs:
      - targets: ["minio-staging.domain.com"]

اگر آپ کے پاس گرافانا ہے تو اپنا ڈیش بورڈ آئی ڈی حاصل کریں۔ 13502 ایک فوری جائزہ حاصل کریں (صلاحیت، درخواست کی شرح، تاخیر، غلطیوں کی تعداد)۔

14. ٹربل شوٹنگ چیٹ شیٹ

علامت ممکنہ وجہ ٹھیک کریں
SignatureDoesNotMatch پہلے سے دستخط شدہ PUT پر براؤزر نے کچھ اور بھیجا ہے۔ Content-Type دستخط کے مقابلے میں اسی طرح خرچ کریں Content-Type PUT کے دوران ہیڈر
پہلے سے دستخط شدہ URLs مقامی طور پر کام کرتے ہیں، لیکن براؤزر میں نہیں۔ MINIO_SERVER_URL چونکہ یہ سیٹ نہیں ہے، اس لیے یو آر ایل پر دستخط کیے جائیں گے۔ minio:9000 سیٹ MINIO_SERVER_URL=https://minio-staging.domain.com اور دوبارہ شروع کریں
403 SignatureDoesNotMatch Cloudflare سے گزرنے کے بعد Cloudflare ہیڈر کو ہٹاتا/ترمیم کرتا ہے۔ اپنے DNS ریکارڈز کو اس پر سیٹ کریں: صرف DNS (سرمئی بادل)
NoSuchBucket غلط اینڈ پوائنٹ یا بالٹی کی طرف اشارہ کرنے والی ایپ دوبارہ چیک کریں S3_ENDPOINT اور S3_BUCKET ماحول میں
براؤزر CORS عملدرآمد سے پہلے ناکام ہو جاتا ہے۔ آپ کی بالٹی میں CORS کے کوئی اصول نہیں ہیں۔ §12.1 کا CORS JSON نفاذ
اپ لوڈ چھوٹی فائلوں کے لیے کام کرتا ہے، لیکن 100MB کے لیے ناکام ہوتا ہے۔ کلاؤڈ فلیئر فری پلان باڈی کی حدود Cloudflare ادا شدہ منصوبہ استعمال کریں یا CF پراکسی کو چھوڑ دیں۔
x509: certificate signed by unknown authority آپ کی ایپ میں ایپ کنٹینر Let's Encrypt پر بھروسہ نہیں کرتا ہے۔ CA بنڈل اپ ڈیٹ (apt install ca-certificates) یا Docker نیٹ ورک کے اندر HTTP استعمال کریں۔
ویب کنسول کو ری ڈائریکٹ کیا جائے گا: http://minio:9001/login MINIO_BROWSER_REDIRECT_URL چلا گیا اسے مندرجہ ذیل ترتیب دیں۔ https://minio-console-staging.domain.com

مفید تشخیص:

# Check MinIO health
curl -I https://minio-staging.domain.com/minio/health/live

# List all objects in a bucket
docker exec -it minio-staging mc ls --recursive local/domain-files-staging

# Tail MinIO logs
docker compose -f docker-compose.staging.yml logs -f minio

# Decode a presigned URL to see what it was signed for
echo "" | tr '&' 'n'

15. نتیجہ

ہمارے پاس اس وقت جو معلومات ہیں وہ درج ذیل ہیں:

  • ایک مفت S3 سے مطابقت رکھنے والا آبجیکٹ اسٹور جو آپ کے اپنے اسٹیجنگ سرور پر چلتا ہے۔

  • آپ کے حقیقی ڈومین پر حقیقی HTTPS (https://minio-staging.domain.com)، Traefik + آئیے انکرپٹ کا شکریہ۔

  • اسکوپڈ سب سے کم استحقاق والا ایپلیکیشن صارف — روٹ کلید مقفل ہے۔

  • درست کوڈ کا راستہ اسٹیجنگ اور پروڈکشن میں ایک جیسا ہے۔ MinIO/R2/Hetzner/AWS S3 کے درمیان سوئچ کرنا env فائل میں چار متغیرات کی تبدیلی ہے۔

  • ایک پہلے سے دستخط شدہ PUT URL جو صارفین کو API کو نظرانداز کرتے ہوئے براہ راست اسٹوریج میں اپ لوڈ کرنے کی اجازت دیتا ہے۔

  • پہلے سے دستخط شدہ GET یو آر ایل اس بات کو یقینی بناتے ہیں کہ ذاتی دستاویزات کی عمر کم ہے اور توثیق محدود ہے۔

  • ایک لائف سائیکل اصول جو خود بخود پرانی ٹیسٹ فائلوں کو نیوکلیٹس کرتا ہے۔

  • کولڈ بیک اپ بالٹیوں کی اختیاری ہفتہ وار عکس بندی۔

اہم SLAs کے ساتھ منظم اسٹوریج پر پیداوار جاری ہے۔ سٹیجنگ کے اخراجات اب بالکل درست ہیں۔ $0 فی اپ لوڈ کردہ گیگا بائٹ فی مہینہ - اور ہم آخر کار QA کو یہ بتانا بند کر سکتے ہیں کہ "جب آپ کام کر لیں تو ٹیسٹ فائلوں کو حذف کر دیں۔"

اضافی وسائل

اگر یہ گائیڈ آپ کی ٹیم کو چند ڈالر بچاتا ہے، تو اسے دوسری ٹیموں کے ساتھ شیئر کریں جو اب بھی $90/ماہ کی S3 بالٹی میں ٹیسٹ پی ڈی ایف اپ لوڈ کر رہی ہیں۔ مبارک شپنگ.

اوپر تک سکرول کریں۔