diff --git a/서버작업이력.md b/서버작업이력.md new file mode 100644 index 00000000..5a711d96 --- /dev/null +++ b/서버작업이력.md @@ -0,0 +1,231 @@ +# 서버 작업 이력 + +> 서버: mng.codebridge-x.com (114.203.209.83) +> 접속 계정: pro / sampass + +--- + +## 2026-01-30 + +### 1. Nginx client_max_body_size 설정 (413 오류 해결) + +**문제**: 명함 이미지 업로드 시 `413 Content Too Large` 오류 발생 + +**작업 내용**: +```bash +sudo nano /etc/nginx/sites-available/codebridge-x +``` + +`mng.codebridge-x.com` 서버 블록에 추가: +```nginx +server { + server_name mng.codebridge-x.com; + client_max_body_size 20M; # 추가됨 + ... +} +``` + +```bash +sudo nginx -t +sudo systemctl reload nginx +``` + +--- + +### 2. shared-storage 디렉토리 생성 + +**문제**: `Unable to create a directory at /var/www/shared-storage/tenants` 오류 발생 +- 서버 환경은 Docker가 아니므로 `/var/www/` 경로가 존재하지 않음 + +**작업 내용**: +```bash +sudo mkdir -p /home/webservice/shared-storage/tenants +sudo chown -R www-data:www-data /home/webservice/shared-storage +sudo chmod -R 775 /home/webservice/shared-storage +``` + +**결과 확인**: +```bash +ls -la /home/webservice/shared-storage/ +# drwxrwsr-x 3 www-data www-data 4096 Jan 30 14:19 . +# drwxrwsr-x 2 www-data www-data 4096 Jan 30 14:19 tenants +``` + +--- + +### 3. MNG .env 파일에 TENANT_STORAGE_PATH 추가 + +**작업 내용**: +```bash +# .env 파일에 추가 +echo 'TENANT_STORAGE_PATH=/home/webservice/shared-storage/tenants' >> /home/webservice/mng/.env +``` + +**설정 확인**: +```bash +grep TENANT_STORAGE /home/webservice/mng/.env +# TENANT_STORAGE_PATH=/home/webservice/shared-storage/tenants +``` + +--- + +### 4. Laravel 캐시 클리어 및 PHP-FPM 재시작 + +**작업 내용**: +```bash +cd /home/webservice/mng +php artisan config:clear +php artisan cache:clear +php artisan route:clear +php artisan view:clear + +sudo systemctl restart php8.4-fpm +``` + +**설정 반영 확인**: +```bash +php artisan tinker --execute="echo config('filesystems.disks.tenant.root');" +# /home/webservice/shared-storage/tenants +``` + +--- + +### 5. AI 설정 메뉴 추가 + +**문제**: 로컬에는 있던 "AI 설정" 메뉴가 서버에 없음 + +**작업 내용** (tinker 사용): +```bash +cd /home/webservice/mng +php artisan tinker --execute=' +use App\Models\Commons\Menu; +$s = Menu::where("tenant_id", 1)->where("name", "시스템")->first(); +if ($s) { + $a = Menu::where("tenant_id", 1)->where("parent_id", $s->id)->where("url", "/system/ai-config")->first(); + if ($a) { + echo "AI menu exists: " . $a->id; + } else { + $n = Menu::create([ + "tenant_id" => 1, + "parent_id" => $s->id, + "name" => "AI 설정", + "url" => "/system/ai-config", + "is_active" => true, + "sort_order" => 3, + "hidden" => false, + "icon" => "cpu" + ]); + echo "Created: " . $n->id; + } +} +' +``` + +--- + +### 6. AI Config 데이터 추가 (Gemini, GCS) + +**작업 내용** (tinker 사용): +```bash +cd /home/webservice/mng +php artisan tinker --execute=' +use App\Models\System\AiConfig; + +$configs = [ + [ + "name" => "Gemini for Google Cloud API", + "provider" => "gemini", + "api_key" => "vertex_ai_service_account", + "model" => "gemini-2.0-flash", + "base_url" => "https://generativelanguage.googleapis.com/v1beta", + "description" => null, + "is_active" => true, + "options" => [ + "region" => "us-central1", + "auth_type" => "vertex_ai", + "project_id" => "codebridge-chatbot", + "service_account_path" => "/home/webservice/sales/apikey/google_service_account.json" + ], + ], + [ + "name" => "Production GCS", + "provider" => "gcs", + "api_key" => "gcs_service_account", + "model" => "-", + "base_url" => "https://storage.googleapis.com", + "description" => "음성 녹음 파일 백업용 (본사 연구)", + "is_active" => true, + "options" => [ + "bucket_name" => "codebridge-speech-audio-files", + "service_account_path" => "/home/webservice/sales/apikey/google_service_account.json" + ], + ], +]; + +foreach ($configs as $config) { + $existing = AiConfig::where("name", $config["name"])->first(); + if ($existing) { + echo "Already exists: " . $config["name"] . "\n"; + } else { + AiConfig::create($config); + echo "Created: " . $config["name"] . "\n"; + } +} +' +``` + +--- + +### 7. AI Config service_account_path 경로 수정 + +**문제**: Docker 환경 경로 `/var/www/sales/apikey/...`가 서버에서 작동하지 않음 + +**작업 내용** (tinker 사용): +```bash +cd /home/webservice/mng +php artisan tinker --execute=' +use App\Models\System\AiConfig; + +$configs = AiConfig::all(); +foreach ($configs as $config) { + $options = $config->options ?? []; + if (isset($options["service_account_path"])) { + $oldPath = $options["service_account_path"]; + $newPath = str_replace("/var/www/sales/", "/home/webservice/sales/", $oldPath); + if ($oldPath !== $newPath) { + $options["service_account_path"] = $newPath; + $config->options = $options; + $config->save(); + echo "Updated " . $config->name . ": " . $newPath . "\n"; + } + } +} +echo "Done.\n"; +' +``` + +--- + +### 8. SalesRoleSeeder 실행 + +**문제**: 서버에 영업 관련 역할(권한)이 없음 + +**작업 내용**: +```bash +cd /home/webservice/mng +php artisan db:seed --class=SalesRoleSeeder +``` + +--- + +## 참고: Docker vs 서버 경로 차이 + +| 항목 | Docker (로컬) | 서버 | +|------|--------------|------| +| 웹 루트 | `/var/www/` | `/home/webservice/` | +| MNG 앱 | `/var/www/mng/` | `/home/webservice/mng/` | +| API 앱 | `/var/www/api/` | `/home/webservice/api/` | +| Sales 앱 | `/var/www/sales/` | `/home/webservice/sales/` | +| 공유 스토리지 | `/var/www/shared-storage/` | `/home/webservice/shared-storage/` | + +서버에 새로운 설정을 추가할 때는 경로 차이를 반드시 확인해야 합니다.