You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PERN栈下配置S3绑定域名或使用EC2实现图片上传访问

Hey there! Let's break down your two main goals here—binding sub.example.com to your S3 bucket for cleaner image URLs, and setting up direct image uploads/storage on EC2. I'll walk you through both step-by-step, tailored for your PERN stack setup.

Option 1: Bind sub.example.com to S3 (Cleaner Image URLs)

Since you're already storing images in S3, this is the simpler, more scalable option. Here's how to map your custom domain to S3:

Step 1: Rename your S3 Bucket (Critical!)

S3 requires your bucket name to exactly match your custom domain (sub.example.com). If your current bucket has a different name, create a new one with the correct name and migrate your existing images over (or update your upload logic to use the new bucket).

Step 2: Enable Static Website Hosting on S3

  1. Go to your S3 bucket's "Properties" tab.
  2. Scroll to "Static website hosting" and click "Edit".
  3. Select "Enable", set an index document (e.g., index.html—even though you're serving images, this is required), and note the Static website endpoint (it'll look like sub.example.com.s3-website-[region].amazonaws.com).
  4. Save changes.

Step 3: Configure Bucket Permissions for Public Access

You need to make sure images are publicly accessible (but don't overdo it—lock down permissions as much as possible):

  • Option A (Recommended): Bucket Policy for Specific Paths
    Go to the "Permissions" tab, select "Bucket policy", and paste this (replace sub.example.com with your bucket name and adjust the path if needed):
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": "*",
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::sub.example.com/uploads/images/*"
        }
      ]
    }
    
  • Option B: Auto-Set Public Read on Upload
    When uploading images from your Node.js backend, add ACL: 'public-read' to your S3 upload params:
    const uploadParams = {
      Bucket: 'sub.example.com',
      Key: `uploads/images/${fileName}`,
      Body: fileBuffer,
      ACL: 'public-read' // Add this line
    };
    

Step 4: Map Your Domain to S3 via DNS

Head to your domain registrar (or Route 53 if you use AWS for DNS) and add a CNAME record:

  • Hostname: sub.example.com
  • Value: The S3 static website endpoint you noted earlier (omit http:// or https://)

Step 5 (Optional): Add HTTPS with CloudFront

S3's static website doesn't support HTTPS for custom domains natively, so use CloudFront to add encryption and caching:

  1. Create a new CloudFront distribution:
    • Origin domain: Paste your S3 static website endpoint
    • Origin path: Leave blank
    • Viewer protocol policy: Redirect HTTP to HTTPS
    • Alternate domain names (CNAMEs): sub.example.com
    • Custom SSL certificate: Use AWS Certificate Manager (ACM) to request a free certificate for sub.example.com (must be in the us-east-1 region for CloudFront)
  2. Update your DNS CNAME record to point to the CloudFront distribution domain (instead of the S3 endpoint)
  3. Now your image URLs will be https://sub.example.com/uploads/images/image1.png

Update Your PERN Backend

Instead of storing the default S3 URL, construct your custom URL using the image's S3 key:

// After uploading to S3, get the key (e.g., 'uploads/images/image1.png')
const customImageUrl = `https://sub.example.com/${s3Key}`;
// Save this URL to your PostgreSQL database
await pool.query('INSERT INTO images (url) VALUES ($1)', [customImageUrl]);
Option 2: Direct Image Uploads & Storage on EC2

If you prefer to handle storage directly on EC2, here's how to set this up securely and reliably:

Step 1: Prepare EC2 Storage

Avoid using EC2's temporary instance storage (data is lost on reboot)—use an EBS volume instead:

  1. Attach an EBS volume to your EC2 instance (size based on your storage needs)
  2. Mount the volume to a directory like /var/www/uploads/images:
    sudo mkdir -p /var/www/uploads/images
    sudo mount /dev/xvdf /var/www/uploads/images # Replace xvdf with your EBS device name
    # Add to fstab to auto-mount on reboot
    echo '/dev/xvdf /var/www/uploads/images ext4 defaults 0 0' | sudo tee -a /etc/fstab
    
  3. Set permissions so your Node.js process can write to the directory:
    sudo chown -R $USER:$USER /var/www/uploads/images
    sudo chmod -R 755 /var/www/uploads/images
    

Step 2: Configure Express to Handle Uploads

Use the multer middleware to handle file uploads in your Node.js backend:

  1. Install multer:
    npm install multer
    
  2. Set up multer storage in your Express app:
    const multer = require('multer');
    
    // Configure storage destination and filename logic
    const storage = multer.diskStorage({
      destination: (req, file, cb) => {
        cb(null, '/var/www/uploads/images');
      },
      filename: (req, file, cb) => {
        // Generate a unique filename to avoid overwrites
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
        const fileExt = file.originalname.split('.').pop();
        cb(null, `image-${uniqueSuffix}.${fileExt}`);
      }
    });
    
    // Filter to only allow image files (optional but recommended)
    const fileFilter = (req, file, cb) => {
      if (file.mimetype.startsWith('image/')) {
        cb(null, true);
      } else {
        cb(new Error('Only image files are allowed!'), false);
      }
    };
    
    const upload = multer({ storage: storage, fileFilter: fileFilter });
    
  3. Create an upload route:
    app.post('/api/upload-image', upload.single('image'), async (req, res) => {
      try {
        if (!req.file) {
          return res.status(400).json({ error: 'No image file provided' });
        }
        // Construct the public URL
        const imageUrl = `https://sub.example.com/uploads/images/${req.file.filename}`;
        // Save to PostgreSQL
        await pool.query(
          'INSERT INTO images (url, filename) VALUES ($1, $2) RETURNING *',
          [imageUrl, req.file.filename]
        );
        res.status(200).json({ url: imageUrl });
      } catch (err) {
        console.error('Upload error:', err);
        res.status(500).json({ error: 'Failed to upload image' });
      }
    });
    

Step 3: Set Up Nginx to Serve Static Images & Proxy API Requests

Using Nginx is safer than exposing Express directly to the internet—it handles static files efficiently and adds a layer of security:

  1. Install Nginx on your EC2 instance:
    sudo apt update && sudo apt install nginx -y # For Ubuntu/Debian
    # Or for Amazon Linux: sudo yum install nginx -y
    
  2. Create a new Nginx config file for sub.example.com:
    sudo nano /etc/nginx/sites-available/sub.example.com
    
  3. Paste this config (adjust port if your Express app runs on something other than 3000):
    server {
        listen 80;
        server_name sub.example.com;
    
        # Serve static images from EBS volume
        location /uploads/images/ {
            root /var/www;
            expires 30d; # Cache images for 30 days to reduce load
            add_header Cache-Control "public, max-age=2592000";
        }
    
        # Proxy API requests to Express
        location /api/ {
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    
        # Redirect root to your frontend (optional)
        location / {
            proxy_pass http://your-frontend-url.com; # Or point to static frontend files
        }
    }
    
  4. Enable the config and restart Nginx:
    sudo ln -s /etc/nginx/sites-available/sub.example.com /etc/nginx/sites-enabled/
    sudo nginx -t # Test config for errors
    sudo systemctl restart nginx
    

Step 4: Add HTTPS with Let's Encrypt

Get a free SSL certificate to enable HTTPS:

  1. Install Certbot:
    sudo apt install certbot python3-certbot-nginx -y # Ubuntu/Debian
    # Amazon Linux: sudo yum install certbot python3-certbot-nginx -y
    
  2. Request and install the certificate:
    sudo certbot --nginx -d sub.example.com
    
    Follow the prompts—Certbot will auto-update your Nginx config to redirect HTTP to HTTPS.

Step 5: Configure EC2 Security Group

Make sure your EC2 security group allows inbound traffic on ports 80 (HTTP) and 443 (HTTPS) from all sources (or restrict to your frontend IP if needed).

Key Notes for EC2 Setup

  • Backup EBS Volumes: Regularly create snapshots of your EBS volume to prevent data loss.
  • Scalability: EC2 storage isn't as scalable as S3—if you expect high traffic or large storage needs, consider syncing images to S3 in the background.
  • Performance: For large image libraries, add a CDN (like CloudFront) to cache images globally.

Which Option Should You Choose?

  • Go with S3 + Custom Domain if you want low maintenance, high scalability, and built-in reliability. It's the AWS-native approach and perfect for most image storage use cases.
  • Go with EC2 only if you need full control over the storage environment, or have specific requirements that S3 doesn't meet (like custom processing on upload that's easier to run on EC2).

内容的提问来源于stack exchange,提问作者Hamza Zeb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:26:47