# Как обойти ограничение окружения в 4 КБ на Vercel **Published by:** [klif](https://paragraph.com/@klifentro/) **Published on:** 2022-12-30 **URL:** https://paragraph.com/@klifentro/4-vercel ## Content В Layer3, мы запускаем всю нашу платформу в прекрасно организованном full-stack окружении на Vercel. Весь серверный и клиентский код написан на TypeScript и использует многие модули и типы. Все шло хорошо, пока однажды…У Vercel есть ограничение на переменную окружения в 4 КБ. Это вызвано базовой инфраструктурой AWS Lambda, но, хотя у AWS есть некоторые решения для правильного управления секретами, Vercel в основном говорит, что вам нужно создать собственное управление секретами. В это время, у платформы Vercel, есть так много плюсов, и мы сохраняем так много времени, поскольку нам не нужно настраивать сложную облачную инфраструктуру на AWS. Поэтому мы решили исправить это. Наше решение сфокусировано на двух вещах:Безопасное управление и развертывание секретов при просмотре и производствеСохраняйте отличный опыт разработчика перенося ключи разработки в локальные окруженияПосмотрите пример репозитория здесь: larskarbo/next-env-encrypt-decryptПознакомьтесь с Doppler - менеджером по окружениюDoppler - это сервис, который специализируется на управлении переменными окружения. Это звучало идеально для нашего варианта использования, у них даже есть интеграция с Vercel!Однако мы быстро осознали, что хотя у Doppler есть интеграция с Vercel, это вовсе не решает проблему 4 КБ. На самом деле, он просто - вроде как способствует этому... Добавляя больше переменных DOPPLER_. Однако, интерфейс Doppler и API удивительные, и мы подумали, что могли бы создать работающее решение с некоторыми взломами.Извлечение секретов из Doppler вместо VercelКак только вы добавите все свои переменные окружения в Doppler вместо Vercel, вы сможете довольно легко обойти ограничение в 4 КБ, извлекая секреты из Doppler вместо Vercel.Единственная переменная окружения, которая вам нужна в Vercel, - это токен Doppler. Самый простой способ добавить токены для developmentи preview - production это установить Vercel CLI и Doppler CLI и сгенерировать три разных ключа из терминала:echo -n "$(doppler configs tokens create vercel-gitops --config dev --plain)" | vercel env add DOPPLER_TOKEN development echo -n "$(doppler configs tokens create vercel-gitops --config stg --plain)" | vercel env add DOPPLER_TOKEN preview echo -n "$(doppler configs tokens create vercel-gitops --config prd --plain)" | vercel env add DOPPLER_TOKEN production Затем мы создадим скрипт fetchSecrets.ts, который извлекает эти переменные во время создания и записывает их в .env.import fs from "fs/promises"; import secrets from "@larskarbo/gitops-secrets"; async function main() { const payload = await secrets.providers.doppler.fetch(); let envFile = ""; Object.entries({ ...payload, }).forEach(([key, value]) => { envFile += `${key}=${value}\n`; }); envFile += `DOPPLER_TOKEN=${process.env.DOPPLER_TOKEN}\n`; await fs.writeFile(".env", envFile); } void main(); Изменения в package.json:"scripts": { ... "build": "npm run fetch-secrets && nextjs build", "fetch-secrets": "ts-node fetchSecrets.ts" } Да, это все, что вам нужно. В разработке, вы просто запустите npm run fetch-env. Этот процесс не добавляет много движущихся частей и ощущается очень схоже на рабочий процесс vercel env pull.Делаем шаг вперед с зашифрованными секретамиТеперь, когда мы создаем собственное управление секретами, почему бы не сделать шаг вперед и улучшить безопасность? Текущая настройка переменной окружения может представлять угрозу безопасности. Мошеннический npm пакет мог бы сбросить все свободно доступные переменные process.env и отправить их на отдаленный сервер. И помните, это также могло бы быть зависимостью одной из ваших зависимостей. У большинства npm приложений есть куча зависимостей, когда вы смотрите на дерево зависимостей, поэтому область поверхностного риска может быть больше, чем вы думаете. Нашей целью будет создание системы, где:Секреты всегда защифрованы, как при передаче, так и при хранении.Секретам сложно непреднамеренно утечь, когда они потребляются конечным приложением.У многих платформ для этого есть сложные решения такие, как AWS KMS и Docker Secrets. Идея в том, что эти инструменты хранят секрет в зашифрованной форме и предоставляют его приложению во время выполнения. Мы решим это простым и индивидуальным способом с некоторыми уникальными соображениями:Нам нужно, чтобы переменные NEXT_PUBLIC_ были доступны в окружении.Мы хотим быть в состоянии переопределять секреты с .env.local для наших локальных окружений разработки.Основываясь на настройке Doppler, мы добавим в Vercel другую переменную окружения, SECRETS_KEY. gen_key () { openssl rand -base64 32 } gen_key | vercel env add SECRETS_KEY development gen_key | vercel env add SECRETS_KEY preview gen_key | vercel env add SECRETS_KEY production Теперь мы сделаем некоторые изменения в наш скрипт fetch-secrets.ts. Это нужно, чтобы:Извлечь секреты из DopplerЗаписать все переменные NEXT_PUBLIC_ в .envЗаписать все остальные секреты в специальный файл .encrypted-secretsЗафиксируйте этот файл в git вот так, а затем добавьте его в .gitignore. Это позволяет нам запускать приложение независимо от сгенерированного файла. Наши супер-заряженные fetch-secrets.ts выглядят так:import Cryptr from "cryptr"; import fs from "fs/promises"; import gitopsSecrets from "@larskarbo/gitops-secrets"; import { ENCRYPTED_SECRETS_FILE } from "../src/utils"; async function main() { const payload = await gitopsSecrets.providers.doppler.fetch(); if (!process.env.SECRETS_KEY) { throw new Error("SECRETS_KEY is not set"); } const cryptr = new Cryptr(process.env.SECRETS_KEY); const encryptedText = cryptr.encrypt(JSON.stringify(payload)); await fs.writeFile(ENCRYPTED_SECRETS_FILE, encryptedText); let envFile = ""; Object.entries({ ...payload, }) .filter(([key]) => key.startsWith("NEXT_PUBLIC_")) .forEach(([key, value]) => { envFile += `${key}=${value}\n`; }); envFile += `DOPPLER_TOKEN=${process.env.DOPPLER_TOKEN}\n`; envFile += `SECRETS_KEY=${process.env.SECRETS_KEY}\n`; await fs.writeFile(".env", envFile); } void main(); Затем нам нужно расшифровать секреты в коде времени выполнения. Мы создадим вспомогательную функцию для этого.let decryptedSecrets: null | { [key: string]: string; } = null; import { readFileSync } from "fs"; import Cryptr from "cryptr"; import path from "path"; export const ENCRYPTED_SECRETS_FILE = ".encrypted-secrets"; export const getSecret = (key: string) => { // in case you have some overrides in `.env.local` if (process.env.NODE_ENV === "development" && process.env[key]) { return process.env[key]; } // only decrypt secrets the first time if (!decryptedSecrets) { if (!process.env.SECRETS_KEY) { return undefined; } const encryptedSecrets = readFileSync( path.join(process.cwd(), ENCRYPTED_SECRETS_FILE), "utf8" ); const cryptr = new Cryptr(process.env.SECRETS_KEY); decryptedSecrets = JSON.parse(cryptr.decrypt(encryptedSecrets)); } return decryptedSecrets?.[key]; }; Вуаля! Теперь вы можете использовать секреты везде в вашем приложении следующим образом:// back-end const apiKey = getSecret("API_KEY") // front-end const somePublicKey = process.env.NEXT_PUBLIC_KEY Проверьте рабочую демонстрацию здесь: (ссылка, репозиторий в github).ЗаключениеУ Vercel может быть ограничение окружения в 4 КБ, но с некоторой творческой инженерией, вы можете столкнуться с системой, которая будет более удобной для разработчиков и безопасной, чем раньше. Такой подход может быть правильным, если вы являетесь стартапом на ранней стадии. Когда вы станете больше и у вас будут строже требования к управлению конфиденциальными данными, вы, вероятно, столкнетесь с более сложной облачной инфраструктурой. В Layer3, мы используем Vercel и Doppler для быстрого перемещения. Если вам понравился этот пост и вам понравилась идея создания новых типов приложений, которые используют преимущества децентрализованной сети, вам следует присоединиться к нашей команде! ## Publication Information - [klif](https://paragraph.com/@klifentro/): Publication homepage - [All Posts](https://paragraph.com/@klifentro/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@klifentro): Subscribe to updates