Setup S3 configuration

This commit is contained in:
Sam Becker 2023-11-26 12:53:30 -06:00
parent f552cf4fc7
commit 25941329db
4 changed files with 106 additions and 24 deletions

View File

@ -68,6 +68,42 @@ Installation
- `NEXT_PUBLIC_HIDE_REPO_LINK = 1` removes footer link to repo
- `NEXT_PUBLIC_HIDE_FILM_SIMULATIONS = 1` prevents Fujifilm simulations showing up in `/grid` sidebar
### Setup alternate storage
#### AWS S3
1. [Create bucket](https://s3.console.aws.amazon.com/s3) with "Block all public access" turned off
- Setup CORS:
```
[{
"AllowedHeaders": [],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"http://localhost:*",
"{PRODUCTION_DOMAIN}",
"https://*${VERCEL_PROJECT}.vercel.app"
],
"ExposeHeaders": []
}]
```
- Store configuration
- `NEXT_PUBLIC_S3_BUCKET`
- `NEXT_PUBLIC_S3_REGION`
2. [Create IAM policy](https://console.aws.amazon.com/iam/home#/policies) for client uploads (JSON editor recommended)
- Action: `s3:PutObject`
- Resource: `arn:aws:s3:::{BUCKET_NAME}/uploads/*`
3. [Create IAM policy](https://console.aws.amazon.com/iam/home#/policies) for admin actions (JSON editor recommended)
- Action: `s3:PutObject`, `s3:GetObject`, `s3:ListBucket`, `s3:DeleteObject`
- Resource: `arn:aws:s3:::{BUCKET_NAME}`, `arn:aws:s3:::{BUCKET_NAME}/*`
4. [Create IAM user](https://console.aws.amazon.com/iam/home#/users) for upload policy (by choosing "Attach policies directly"), create access key under "Security credentials," choose "Application running outside AWS," and store credentials
- `NEXT_PUBLIC_S3_UPLOAD_ACCESS_KEY`
- `NEXT_PUBLIC_S3_UPLOAD_SECRET_ACCESS_KEY`
5. [Create IAM user](https://console.aws.amazon.com/iam/home#/users), for admin policy (by choosing "Attach policies directly"), , create access key under "Security credentials," choose "Application running outside AWS," and store credentials (_ensure admin environment variables are not prefixed with `NEXT_PUBLIC`_)
- `S3_ADMIN_ACCESS_KEY`
- `S3_ADMIN_SECRET_ACCESS_KEY`
FAQ
-
Q: My images/content have fallen out of sync with my database and/or my production site no longer matches local development. What do I do?<br />

View File

@ -1,24 +1,40 @@
/** @type {import('next').NextConfig} */
const STORE_ID = process.env.BLOB_READ_WRITE_TOKEN?.match(
const VERCEL_BLOB_STORE_ID = process.env.BLOB_READ_WRITE_TOKEN?.match(
/^vercel_blob_rw_([a-z0-9]+)_[a-z0-9]+$/i,
)?.[1].toLowerCase();
const VERCEL_BLOB_HOSTNAME = VERCEL_BLOB_STORE_ID
? `${VERCEL_BLOB_STORE_ID}.public.blob.vercel-storage.com`
: undefined;
const AWS_S3_HOSTNAME =
process.env.NEXT_PUBLIC_S3_BUCKET &&
process.env.NEXT_PUBLIC_S3_REGION
// eslint-disable-next-line max-len
? `${process.env.NEXT_PUBLIC_S3_BUCKET}.s3.${process.env.NEXT_PUBLIC_S3_REGION}.amazonaws.com`
: undefined;
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
imageSizes: [200],
remotePatterns: []
.concat(VERCEL_BLOB_HOSTNAME ? {
protocol: 'https',
hostname: VERCEL_BLOB_HOSTNAME,
port: '',
pathname: '/**',
} : [])
.concat(AWS_S3_HOSTNAME ? {
protocol: 'https',
hostname: AWS_S3_HOSTNAME,
port: '',
pathname: '/**',
} : []),
minimumCacheTTL: 31536000,
},
};
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
const nextConfig = {
images: {
imageSizes: [200],
remotePatterns: [{
protocol: 'https',
hostname: `${STORE_ID}.public.blob.vercel-storage.com`,
port: '',
pathname: '/**',
}],
minimumCacheTTL: 31536000,
},
};
module.exports = withBundleAnalyzer(nextConfig);

View File

@ -121,16 +121,30 @@ export default function SiteChecklistClient({
and connect to project
</ChecklistRow>
<ChecklistRow
title="Setup blob store"
title="Setup blob store (one of the following)"
status={hasBlob}
isPending={isPendingPage}
>
{renderLink(
'https://vercel.com/docs/storage/vercel-blob/quickstart',
'Create Vercel Blob store',
)}
{' '}
and connect to project
<ol className="list-decimal list-inside">
<li>
Vercel Blob:
{' '}
{renderLink(
'https://vercel.com/docs/storage/vercel-blob/quickstart',
'create store',
)}
{' '}
and connect to project
</li>
<li>
AWS S3:
{' '}
{renderLink(
'https://github.com/sambecker/exif-photo-blog#aws-s3',
'create/configure bucket',
)}
</li>
</ol>
</ChecklistRow>
</Checklist>
<Checklist

View File

@ -1,5 +1,7 @@
import { makeUrlAbsolute, shortenUrl } from '@/utility/url';
// META / DOMAINS
export const SITE_TITLE =
process.env.NEXT_PUBLIC_SITE_TITLE ||
'Photo Blog';
@ -28,6 +30,20 @@ export const BASE_URL = process.env.NODE_ENV === 'production'
? makeUrlAbsolute(SITE_DOMAIN).toLowerCase()
: 'http://localhost:3000';
// STORAGE
const hasVercelBlob = (process.env.BLOB_READ_WRITE_TOKEN ?? '').length > 0;
const hasAwsS3Storage =
(process.env.NEXT_PUBLIC_S3_BUCKET ?? '').length > 0 &&
(process.env.NEXT_PUBLIC_S3_REGION ?? '').length > 0 &&
(process.env.NEXT_PUBLIC_S3_UPLOAD_ACCESS_ID ?? '').length > 0 &&
(process.env.NEXT_PUBLIC_S3_UPLOAD_SECRET ?? '').length > 0 &&
(process.env.S3_ADMIN_ACCESS_ID ?? '').length > 0 &&
(process.env.S3_ADMIN_ACCESS_SECRET ?? '').length > 0;
// SETTINGS
export const PRO_MODE_ENABLED = process.env.NEXT_PUBLIC_PRO_MODE === '1';
export const PUBLIC_API_ENABLED = process.env.NEXT_PUBLIC_PUBLIC_API === '1';
export const SHOW_REPO_LINK = process.env.NEXT_PUBLIC_HIDE_REPO_LINK !== '1';
@ -38,7 +54,7 @@ export const OG_TEXT_BOTTOM_ALIGNMENT =
export const CONFIG_CHECKLIST_STATUS = {
hasPostgres: (process.env.POSTGRES_HOST ?? '').length > 0,
hasBlob: (process.env.BLOB_READ_WRITE_TOKEN ?? '').length > 0,
hasBlob: hasVercelBlob || hasAwsS3Storage,
hasAuth: (process.env.AUTH_SECRET ?? '').length > 0,
hasAdminUser: (
(process.env.ADMIN_EMAIL ?? '').length > 0 &&