.env 파일에는 데이터베이스 비밀번호, API 키 등 민감한 정보가 포함되어 있어 외부에 노출되면 심각한 보안 문제가 발생할 수 있습니다. 이를 방지하고 해결하는 방법들을 알아보겠습니다.
가장 기본적이고 중요한 설정입니다.
server {
listen 80;
server_name example.com;
root /var/www/html;
# .env 파일 접근 차단
location ~ /\.env {
deny all;
return 404;
}
# 모든 숨김 파일 차단
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
<VirtualHost *:80>
DocumentRoot /var/www/html
# .env 파일 접근 차단
<Files ".env">
Require all denied
</Files>
# 모든 숨김 파일 차단
<FilesMatch "^\.">
Require all denied
</FilesMatch>
</VirtualHost>
Apache 환경에서 .htaccess 파일로 보호하는 방법입니다.
# .env 파일 접근 차단
<Files ".env">
Order allow,deny
Deny from all
</Files>
# 추가 보안 파일들 차단
<FilesMatch "\.(env|log|ini)$">
Order allow,deny
Deny from all
</FilesMatch>
시스템 레벨에서 파일 권한을 제한합니다.
# .env 파일 권한 설정 (소유자만 읽기 가능)
chmod 600 .env
# 웹서버 사용자만 접근 가능하도록 설정
chown www-data:www-data .env
chmod 640 .env
웹 루트 밖으로 .env 파일을 이동시키는 방법입니다.
<?php
class EnvLoader {
public static function load() {
// 웹 루트 밖의 .env 파일 로드
$envPath = dirname(__DIR__, 2) . '/.env';
if (!file_exists($envPath)) {
throw new Exception('.env file not found');
}
$lines = file($envPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($lines as $line) {
if (strpos($line, '=') !== false && strpos($line, '#') !== 0) {
list($key, $value) = explode('=', $line, 2);
$_ENV[trim($key)] = trim($value, '"\'');
}
}
}
}
EnvLoader::load();
민감한 정보가 실수로 출력되지 않도록 검증합니다.
<?php
class EnvValidator {
private static $sensitiveKeys = [
'DB_PASSWORD', 'API_KEY', 'SECRET_KEY',
'JWT_SECRET', 'MAIL_PASSWORD'
];
public static function validateEnv() {
foreach (self::$sensitiveKeys as $key) {
if (empty($_ENV[$key])) {
throw new Exception("Required environment variable $key is missing");
}
}
}
public static function getSafeEnvVars() {
$safe = [];
foreach ($_ENV as $key => $value) {
if (!in_array($key, self::$sensitiveKeys)) {
$safe[$key] = $value;
}
}
return $safe;
}
}
버전 관리에서 .env 파일을 제외합니다.
# 환경 설정 파일
.env
.env.local
.env.production
.env.staging
# 로그 파일
*.log
# 임시 파일
*.tmp
*.cache
개발자들이 참고할 수 있는 템플릿을 제공합니다.
# 데이터베이스 설정
DB_HOST=localhost
DB_NAME=your_database
DB_USER=your_username
DB_PASSWORD=your_password
# API 키 (실제 키로 교체 필요)
API_KEY=your_api_key_here
SECRET_KEY=your_secret_key_here
# 애플리케이션 설정
APP_ENV=production
APP_DEBUG=false
애플리케이션 실행 시 .env 파일 노출 여부를 확인합니다.
<?php
class SecurityChecker {
public static function checkEnvExposure() {
$envUrl = $_SERVER['HTTP_HOST'] . '/.env';
$context = stream_context_create([
'http' => [
'timeout' => 5,
'method' => 'GET'
]
]);
$response = @file_get_contents("http://$envUrl", false, $context);
if ($response !== false && strpos($response, 'DB_PASSWORD') !== false) {
error_log('SECURITY ALERT: .env file is publicly accessible!');
// 관리자에게 알림 발송
self::notifyAdmin();
}
}
private static function notifyAdmin() {
mail('admin@example.com', 'Security Alert', '.env file exposure detected');
}
}
Docker 컨테이너에서 환경변수를 안전하게 관리합니다.
FROM php:8.1-fpm
# .env 파일을 이미지에 포함하지 않음
COPY --chown=www-data:www-data . /var/www/html
RUN rm -f /var/www/html/.env*
# 환경변수는 런타임에 주입
ENV DB_HOST=""
ENV DB_NAME=""
ENV DB_USER=""
ENV DB_PASSWORD=""
version: '3.8'
services:
app:
build: .
environment:
- DB_HOST=database
- DB_NAME=myapp
- DB_USER=user
- DB_PASSWORD_FILE=/run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
.env 파일 접근 시도를 모니터링합니다.
server {
listen 80;
server_name example.com;
location ~ /\.env {
access_log /var/log/nginx/env_access_attempts.log;
deny all;
return 404;
}
}
#!/bin/bash
LOG_FILE="/var/log/nginx/env_access_attempts.log"
if [ -f "$LOG_FILE" ] && [ -s "$LOG_FILE" ]; then
echo "WARNING: .env access attempts detected!"
tail -10 "$LOG_FILE"
# 관리자에게 알림
echo "Suspicious .env access attempts detected" | \
mail -s "Security Alert" admin@example.com
# 로그 파일 초기화
> "$LOG_FILE"
fi
이러한 보안 조치들을 종합적으로 적용하면 .env 파일 노출 위험을 크게 줄일 수 있습니다. 특히 웹서버 설정과 파일 권한 관리는 필수적으로 적용해야 하는 기본 보안 조치입니다.