# 설치 가이드

## 1. 권장 환경

- Linux: Ubuntu 24.04 또는 Rocky Linux 9
- Apache 2.4+
- PHP 8.3+와 Composer 2
- MariaDB 10.11+ (MySQL 8.0 호환)
- Node.js 24 LTS 권장, 최소 22
- Android: Flutter stable, Android SDK, JDK 17+
- iOS: macOS, Flutter stable, Xcode, CocoaPods

기본 `composer.json`은 CodeIgniter 4.7.4 이상을 사용하며 PHP 8.3 이상이 필요합니다.

## 2. PHP 확장

```bash
php -m | grep -E 'intl|mbstring|mysqli|curl|openssl|json|fileinfo'
```

Ubuntu 예:

```bash
sudo apt update
sudo apt install -y apache2 mariadb-server mariadb-client php php-cli php-mysql php-intl php-mbstring php-curl php-xml php-zip php-gd unzip git
```

## 3. 디렉터리

```text
/var/www/flutter-builder
├── web
├── orchestrator
├── flutter_template
├── database
├── scripts
└── runtime
```

Apache DocumentRoot는 `/var/www/flutter-builder/web/public`입니다.

## 4. MariaDB

```bash
mariadb -u root -p < database/schema.sql
mariadb -u root -p appbuilder < database/seed.sql
```

운영 계정 예:

```sql
CREATE USER 'appbuilder'@'127.0.0.1' IDENTIFIED BY '강한비밀번호';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX
ON appbuilder.* TO 'appbuilder'@'127.0.0.1';
FLUSH PRIVILEGES;
```

## 5. PHP 웹

```bash
cd web
composer install --no-dev --optimize-autoloader
cp env .env
```

`.env`:

```dotenv
CI_ENVIRONMENT = production
app.baseURL = 'https://builder.example.com/'
app.forceGlobalSecureRequests = true
cookie.secure = true

database.default.hostname = 127.0.0.1
database.default.database = appbuilder
database.default.username = appbuilder
database.default.password = CHANGE_ME

ORCHESTRATOR_URL = http://127.0.0.1:4100
ORCHESTRATOR_SHARED_SECRET = SAME_LONG_RANDOM_VALUE
APP_MASTER_KEY = BASE64_32_BYTE_KEY
ARTIFACT_ROOT = /var/www/flutter-builder/runtime/artifacts
```

키 생성:

```bash
php -r 'echo base64_encode(random_bytes(32)), PHP_EOL;'
openssl rand -hex 48
```

## 6. Node 오케스트레이터

```bash
cd orchestrator
npm ci
cp .env.example .env
```

Linux Android 워커 예:

```dotenv
NODE_ENV=production
HOST=127.0.0.1
PORT=4100
DB_HOST=127.0.0.1
DB_NAME=appbuilder
DB_USER=appbuilder
DB_PASSWORD=CHANGE_ME
SHARED_SECRET=SAME_AS_PHP
APP_MASTER_KEY=SAME_AS_PHP
WORKER_ENABLED=true
RELEASE_WORKER_ENABLED=true
PLATFORM_ALLOWLIST=android
RELEASE_PROVIDER_ALLOWLIST=google_play
DRY_RUN=true
PROJECT_ROOT=/var/www/flutter-builder
WORKSPACE_ROOT=/var/www/flutter-builder/runtime/workspaces
ARTIFACT_ROOT=/var/www/flutter-builder/runtime/artifacts
FLUTTER_TEMPLATE_ROOT=/var/www/flutter-builder/flutter_template/overlay
FLUTTER_BIN=/opt/flutter/bin/flutter
```

macOS iOS 워커는 별도 프로세스 또는 서버에서 다음처럼 제한합니다.

```dotenv
PLATFORM_ALLOWLIST=ios
RELEASE_PROVIDER_ALLOWLIST=app_store
XCRUN_BIN=/usr/bin/xcrun
```

## 7. 권한

```bash
sudo useradd --system --home /var/lib/builder-worker --shell /usr/sbin/nologin builder-worker || true
sudo chown -R www-data:www-data web/writable
sudo chmod -R 770 web/writable
sudo mkdir -p runtime/workspaces runtime/artifacts
sudo chown -R builder-worker:www-data runtime
sudo chmod -R 2770 runtime
```

Apache가 산출물을 읽어야 하므로 `www-data` 그룹 읽기 권한을 유지하십시오.

## 8. Apache

```bash
sudo cp apache/flutter-builder.conf.example /etc/apache2/sites-available/flutter-builder.conf
sudo a2enmod rewrite headers ssl
sudo a2ensite flutter-builder.conf
sudo apachectl configtest
sudo systemctl reload apache2
```

TLS 적용 후 `cookie.secure=true`와 `app.forceGlobalSecureRequests=true`를 사용하십시오.

## 9. systemd

```bash
sudo cp systemd/flutter-builder-orchestrator.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now flutter-builder-orchestrator
sudo journalctl -u flutter-builder-orchestrator -f
```

Node가 nvm 경로에 설치되어 있다면 `ExecStart`를 실제 절대 경로로 변경하십시오.

## 10. 점검

```bash
./scripts/healthcheck.sh
./scripts/validate_source.sh
curl http://127.0.0.1:4100/health
```

웹 로그인 후 다음 순서로 확인합니다.

1. 샘플 앱 빌더 열기
2. 설정 검증과 저장
3. `DRY_RUN=true` Android와 iOS 빌드 작업
4. 빌드 로그와 AAB 모형 산출물 다운로드
5. 스토어 연결정보 등록
6. 실제 계정 업로드 전 별도 테스트 앱으로 검증

## 11. 실제 빌드 전환

`DRY_RUN=false` 전에 확인:

- `flutter doctor` 정상
- Android SDK 라이선스와 JDK
- iOS Xcode/CocoaPods 및 코드 서명 환경
- 워커 사용자의 Flutter, Gradle, Xcode 권한
- 앱별 실제 서명 설정
- 스토어 테스트 개발자 계정
- 런타임 디스크 여유와 백업

기본 소스에는 앱별 서명키 자동 주입이 아직 포함되지 않았으므로 [구현 범위·제약](IMPLEMENTATION_STATUS.md)을 확인하십시오.
