Суть урока
.env файл — это связка ключей от дома. Ты НИКОГДА не кладёшь её на крыльцо — не публикуешь на GitHub. Оригинал хранишь в сейфе (1Password), копию передаёшь только системе которой доверяешь (Cloudflare Secrets). Этот урок о том как правильно обращаться с API ключами чтобы не потерять ни деньги ни репутацию.
Ключевые концепции
- .env файл — файл с переменными окружения, хранит секреты локально, никогда не попадает в Git
- process.env — способ читать переменные из .env в коде (Node.js) или
os.environ(Python) - wrangler secret — безопасное хранение секретов в Cloudflare Workers для продакшна
- 1Password — менеджер паролей для хранения всех API ключей в зашифрованном виде
- .gitignore — список файлов которые Git игнорирует (туда идёт
.env) - Dev vs Prod secrets — разные ключи для разработки и продакшна (лимиты, права доступа)
- Ротация ключей — регулярная замена ключей как мера безопасности
Теория
Почему это важно: цена ошибки
Типичные истории с форумов и из GitHub Issues:
- Разработчик случайно закоммитил AWS ключ → боты находят такие ключи за считанные минуты → за ночь приходит счёт на тысячи долларов
- Anthropic ключ в публичном репо → кто-то потратил весь лимит за выходные → проект упал
- Google API ключ без ограничений → спам-боты использовали его для атак
Ключ в открытом GitHub репо — это деньги на дороге. Кто-то подберёт.
Структура безопасной работы с ключами
Три уровня хранения:
1Password (мастер-хранилище)
↓ копируешь вручную
.env (локальная разработка)
↓ Claude Code читает через process.env
↓ НЕ попадает в Git (.gitignore)
↓ при деплое
Cloudflare Secrets / wrangler secret (продакшн)Правило одного источника: 1Password — это единственное место где хранятся оригиналы. Всё остальное — временные копии.
Шаг 1: Создай .gitignore правильно
До того как создавать что-либо ещё — создай .gitignore в корне проекта:
# Секреты — НИКОГДА не в Git
.env
.env.local
.env.*.local
.env.production
# Логи
logs/
*.log
npm-debug.log*
# Зависимости
node_modules/
__pycache__/
*.pyc
# Системные
.DS_Store
.cursor/Проверка что .env игнорируется:
git status
# .env не должен появляться в списке файловЕсли .env уже попал в Git (ошибка):
git rm --cached .env
git commit -m "Remove .env from tracking"
# Смени все ключи которые были в этом файле!Реальная структура .env файла для типичного проекта
Вот как выглядит реальная организация переменных окружения в рабочем проекте:
project-root/
├── .env ← Реальные ключи (НЕ в Git!)
├── .env.example ← Шаблон без значений (в Git)
├── .env.test ← Mock-ключи для тестов (не в Git)
├── .gitignore ← Содержит .env, .env.local, .env.*.local
├── validate-env.js ← Скрипт проверки наличия ключей
└── wrangler.toml ← Конфиг Cloudflare Workers (в новых проектах Cloudflare создаёт wrangler.jsonc; формат toml тоже поддерживается). Prod секреты через wrangler secretШаг 2: Создай .env.example (шаблон без значений)
Этот файл идёт в Git — он показывает какие переменные нужны, но без реальных значений:
# .env.example — COMMIT THIS FILE
# === Anthropic ===
# Получить: platform.claude.com → Settings → API Keys → Create Key
ANTHROPIC_API_KEY=sk-ant-your-key-here
# === Perplexity (для поиска) ===
# Получить: perplexity.ai → Settings → API
PERPLEXITY_API_KEY=pplx-your-key-here
# === Gmail API ===
# Получить: Google Cloud Console → Credentials → OAuth 2.0
GMAIL_CLIENT_ID=your-client-id.apps.googleusercontent.com
GMAIL_CLIENT_SECRET=GOCSPX-your-secret
GMAIL_REFRESH_TOKEN=1//your-refresh-token
# === Google Sheets ===
# ID из URL таблицы: docs.google.com/spreadsheets/d/THIS-IS-ID/edit
GOOGLE_SHEETS_ID=your-spreadsheet-id
# === Настройки приложения ===
NODE_ENV=development
LOG_LEVEL=infoЗатем скопируй в реальный .env и заполни значениями:
cp .env.example .env
# Открой .env и замени all "your-key-here" реальными ключамиШаг 3: Читай переменные в коде
Node.js / JavaScript:
// Установи пакет: npm install dotenv
require('dotenv').config();
// Читай переменные
const anthropicKey = process.env.ANTHROPIC_API_KEY;
const sheetsId = process.env.GOOGLE_SHEETS_ID;
// Проверка наличия перед запуском
function validateEnv() {
const required = ['ANTHROPIC_API_KEY', 'GMAIL_CLIENT_ID'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
throw new Error(`Missing required env vars: ${missing.join(', ')}`);
}
}
validateEnv(); // Вызови в начале приложенияPython:
import os
from dotenv import load_dotenv
load_dotenv() # pip install python-dotenv
anthropic_key = os.environ.get('ANTHROPIC_API_KEY')
if not anthropic_key:
raise ValueError("ANTHROPIC_API_KEY не найден в .env")Что НИКОГДА не делать:
// ❌ Так нельзя — ключ виден в коде
const client = new Anthropic({ apiKey: "sk-ant-abc123..." });
// ✅ Так правильно
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });Шаг 4: Dev vs Prod — разные ключи для разных окружений
Почему разные ключи:
- Prod ключ имеет высокий лимит → случайная ошибка в разработке дорого стоит
- Dev ключ можно легко отозвать не затронув продакшн
- Разные права доступа (dev — read-only, prod — full)
Структура файлов:
.env ← локальная разработка (не в Git)
.env.test ← для тестов (можно с mock-ключами, не в Git)
.env.production ← не используется напрямую (секреты в Cloudflare)Переключение окружений:
const env = process.env.NODE_ENV || 'development';
console.log(`Running in ${env} mode`);
// development → читает .env
// production → секреты приходят через объект env воркера (см. шаг 5)Шаг 5: Cloudflare Secrets для продакшна
Когда деплоишь на Cloudflare Workers — НЕ передаёшь .env. Используешь wrangler secret:
# Установка одного секрета (wrangler спросит значение интерактивно)
wrangler secret put ANTHROPIC_API_KEY
# Просмотр всех секретов (показывает только имена, не значения)
wrangler secret list
# Удаление секрета
wrangler secret delete OLD_API_KEYПосле установки через wrangler secret — в Cloudflare Worker читаешь так же:
// В Cloudflare Worker env — это специальный объект
export default {
async fetch(request, env) {
const key = env.ANTHROPIC_API_KEY; // Не process.env!
// ...
}
};Шаг 6: 1Password — мастер-хранилище
1Password хранит оригиналы всех ключей. Структура которая работает:
1Password → AI Проекты (отдельный vault)
├── Newsletter Automation
│ ├── Anthropic API Key (prod)
│ ├── Anthropic API Key (dev)
│ ├── Perplexity API Key
│ └── Gmail Credentials
├── Lead Gen Project
│ └── ...
└── Shared Infrastructure
├── Cloudflare API Token
└── GitHub TokenКак использовать 1Password CLI для автоматической подстановки:
# Установка: 1password.com/downloads/command-line
op signin
# Автоматическое заполнение .env из 1Password
op inject -i .env.example -o .envДля этого в .env.example указываешь ссылки на 1Password:
ANTHROPIC_API_KEY=op://AI-Projects/Newsletter/api-keyРотация ключей — когда и как
Когда менять ключи:
- Кто-то из команды ушёл
- Подозрение на утечку
- Регулярно раз в 3-6 месяцев (хорошая практика)
- После любого инцидента
Процедура:
- Создай новый ключ в консоли сервиса
- Обнови в 1Password
- Обнови
wrangler secret put KEY_NAMEв Cloudflare - Протестируй что продакшн работает
- Отзови старый ключ
Никогда не отзывай сначала старый — сначала добавь новый, проверь, потом убери старый.
Практика
Задание: Безопасная настройка окружения для Newsletter Automation
Создай папку проекта и инициализируй Git:
bash mkdir newsletter-automation && cd newsletter-automation git initСоздай
.gitignore(скопируй шаблон из урока)Создай
.env.exampleсо всеми нужными переменными (без значений)Скопируй в
.envи заполни минимумANTHROPIC_API_KEY:bash cp .env.example .envНапиши
validate-env.js— скрипт проверки что все нужные переменные установлены:bash node validate-env.js # Должно вывести: ✅ All required env vars are setСделай первый коммит — убедись что
.envне в списке:bash git add . git status # .env не должен быть в списке git commit -m "Initial setup with env template"(Опционально) Зайди в 1Password, создай отдельный vault "AI Projects", добавь свой Anthropic ключ
Цель: Рабочее окружение где ни один ключ не попадает в Git, но весь код читает их через process.env.
Инструменты и ресурсы
- Claude Console — создание и управление Anthropic API ключами
- 1Password — менеджер паролей с CLI и team sharing
- 1Password CLI — автоматическое заполнение
.envиз хранилища - dotenv (npm) —
npm install dotenv— загрузка .env в Node.js - python-dotenv (pip) —
pip install python-dotenv— загрузка .env в Python - Cloudflare Workers Secrets — безопасное хранение секретов в продакшне
- wrangler —
npm install -g wrangler— CLI для Cloudflare Workers и secrets - git-secrets — пре-коммит хук который блокирует коммит с ключами
- gitleaks — сканер утечек секретов в Git-репозиториях
Частые ошибки
Ошибка 1: Хардкод ключа "на минутку" "Сейчас быстро проверю, потом уберу" — забыл, закоммитил, ключ в истории Git навсегда. Даже если удалишь файл — в истории коммитов он останется. Правило: ни одного ключа в коде, никогда, даже на секунду.
// ❌ НИКОГДА — даже "временно"
const client = new Anthropic({ apiKey: "sk-ant-abc123..." });
// ✅ ВСЕГДА — через переменную окружения
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });Ошибка 2: Один ключ для dev и prod Ошибка в тестовом скрипте израсходовала лимит production ключа — продакшн упал. Всегда два ключа: dev с низким лимитом, prod с полным.
Ошибка 3: Забыл .gitignore перед первым коммитом .env попал в первый коммит. Теперь даже после git rm --cached .env ключ остаётся в истории. Единственное решение: сменить все ключи из этого файла.
Перекрёстные ссылки
- Создание первого воркфлоу LIVE — практическое применение
.envпри создании newsletter - Деплой — Cloudflare Workers — как перенести секреты из
.envв Cloudflare Workers черезwrangler secret - Разрешения и безопасность — продвинутые практики управления доступом и ротации ключей
Ключевые выводы
.env файл — это локальная связка ключей. В Git идёт только
.env.example— шаблон без значений.
Никогда не хардкоди ключи в код. Даже в приватных репо — репо может стать публичным, или кто-то получит доступ.
Dev и prod — разные ключи. Ошибка в разработке не должна стоить денег или ломать продакшн.
1Password — единственный источник правды. Все остальные хранилища — временные копии.
Следующий урок
Отметка хранится только в этом браузере и никуда не отправляется. Мой прогресс