학교 출석 시스템 설치 패키지 (docker-compose + 원클릭 설치 스크립트)

This commit is contained in:
2026-08-07 14:17:40 +09:00
commit a6474ed524
5 changed files with 221 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
# 이 파일을 .env로 복사한 뒤 값을 채우세요: cp .env.example .env
# 학교 도메인 (DNS A레코드를 이 서버 IP로 미리 연결해두세요. Caddy가 자동으로 HTTPS 인증서를 발급합니다)
DOMAIN=attendance.myschool.ac.kr
# DB 비밀번호 (임의의 강력한 문자열로 변경하세요)
DB_PASSWORD=change_this_password
# 교사 회원가입 시 필요한 인증 코드 (학교마다 다르게 설정)
TEACHER_SECRET_CODE=change_this_secret_code
# /reset-db (출석 DB 초기화) 엔드포인트 보호용 비밀번호
ADMIN_RESET_PASSWORD=change_this_admin_password
+3
View File
@@ -0,0 +1,3 @@
{$DOMAIN} {
reverse_proxy backend:8000
}
+60
View File
@@ -0,0 +1,60 @@
# 다른 학교에 설치하기
이 시스템을 새 학교 서버에 설치하는 절차입니다. 백엔드는 도커로 뜨고, 도메인만 지정하면 HTTPS 인증서는 자동으로 발급됩니다.
## 1. Firebase 프로젝트 만들기 (학교마다 1개씩)
푸시 알림(FCM)과 웹 대시보드 호스팅에 필요합니다.
1. https://console.firebase.google.com 에서 새 프로젝트 생성
2. Flutter 앱 폴더에서 `flutterfire configure` 실행 → 방금 만든 프로젝트 선택
- `lib/firebase_options.dart`, `android/app/google-services.json`이 새 프로젝트 값으로 교체됩니다
3. Firebase 콘솔 → 프로젝트 설정 → Cloud Messaging → **웹 푸시 인증서**에서 VAPID 키 발급 (아래 3번에서 사용)
4. Firebase 콘솔 → 프로젝트 설정 → 서비스 계정 → **새 비공개 키 생성** → `firebase-key.json`으로 저장 (서버에 올릴 파일, 4번에서 사용)
## 2. 안드로이드 앱 ID 변경 (학교마다 다르게)
- `android/app/build.gradle.kts`의 `applicationId`를 학교별 고유 값으로 변경 (예: `com.myschool.attendance`)
- 릴리즈 키스토어 새로 생성하고 `android/key.properties`에 경로/비밀번호 등록 (기존 백산고 릴리즈와 절대 같은 키스토어 쓰지 않기)
## 3. 서버에 백엔드 배포
가장 쉬운 방법 — 설치 스크립트 한 줄:
```bash
curl -fsSL https://hootongerungit.mcv.kr/sihoo/school-attendance-deploy/raw/branch/main/install.sh | bash
```
Docker가 없으면 자동으로 설치하고, 도메인/교사 인증코드를 물어본 뒤 미리 빌드해둔 이미지(`hootongerungit.mcv.kr/sihoo/school-backend`)를 내려받아 바로 실행합니다. (소스코드는 비공개 레포에 있고, 이 이미지는 그 코드로 미리 빌드해서 공개로 올려둔 것 — 설치할 땐 소스코드 접근이 필요 없습니다.)
수동으로 하고 싶다면:
```bash
git clone https://hootongerungit.mcv.kr/sihoo/school-attendance-deploy.git
cd school-attendance-deploy
cp .env.example .env
vi .env # DOMAIN, DB_PASSWORD, TEACHER_SECRET_CODE, ADMIN_RESET_PASSWORD 채우기
# 1-4번에서 만든 firebase-key.json을 이 폴더에 복사
docker compose pull
docker compose up -d
```
- `DOMAIN`으로 지정한 주소의 DNS A레코드를 이 서버의 공인 IP로 미리 연결해두세요 (포트 80/443 오픈 필요). Caddy가 첫 요청부터 자동으로 Let's Encrypt 인증서를 발급합니다.
- `docker compose logs -f backend`로 정상 기동(DB 연결 완료 로그) 확인.
- 백엔드 코드가 업데이트되면 `docker compose pull && docker compose up -d`로 최신 이미지로 갱신하면 됩니다.
## 4. Flutter 앱 빌드 (학교별 서버 주소로)
```bash
flutter build web --release -t lib/main_client_app.dart \
--dart-define=BASE_URL=https://<2번에서 지정한 DOMAIN> \
--dart-define=WEB_VAPID_KEY=<1-3번에서 발급받은 VAPID 키> \
--dart-define=SCHOOL_NAME=<학교 이름>
flutter build apk --release --split-per-abi -t lib/main_client_app.dart \
--dart-define=BASE_URL=https://<DOMAIN> \
--dart-define=WEB_VAPID_KEY=<VAPID 키> \
--dart-define=SCHOOL_NAME=<학교 이름>
```
인자를 안 주면 기존 백산고 서버(backsanhi.mcv.kr) 기본값으로 빌드되니, 새 학교용 빌드에는 반드시 세 값을 다 넘겨야 합니다.
+52
View File
@@ -0,0 +1,52 @@
services:
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_DB: school_management
POSTGRES_USER: school_admin
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U school_admin -d school_management"]
interval: 5s
timeout: 5s
retries: 10
backend:
image: hootongerungit.mcv.kr/sihoo/school-backend:${IMAGE_TAG:-latest}
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
DB_HOST: db
DB_NAME: school_management
DB_USER: school_admin
DB_PASS: ${DB_PASSWORD}
TEACHER_SECRET_CODE: ${TEACHER_SECRET_CODE}
ADMIN_RESET_PASSWORD: ${ADMIN_RESET_PASSWORD}
FIREBASE_KEY_PATH: /run/secrets/firebase-key.json
volumes:
- ./firebase-key.json:/run/secrets/firebase-key.json:ro
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
DOMAIN: ${DOMAIN}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
depends_on:
- backend
volumes:
db_data:
caddy_data:
caddy_config:
+93
View File
@@ -0,0 +1,93 @@
#!/usr/bin/env bash
# 🏫 학교 출석 시스템 원클릭 설치 스크립트
# 사용법: curl -fsSL <이 파일의 raw 주소> | bash
set -euo pipefail
REPO_URL="https://hootongerungit.mcv.kr/sihoo/school-attendance-deploy.git"
INSTALL_DIR="school-attendance"
echo "🏫 학교 출석 시스템 설치를 시작합니다."
echo ""
# ── 1. Docker 확인/설치 ──────────────────────────────────────
if ! command -v docker &> /dev/null; then
echo "🐳 Docker가 없어서 자동으로 설치합니다..."
curl -fsSL https://get.docker.com | sh
else
echo "✅ Docker 확인됨"
fi
if ! docker compose version &> /dev/null; then
echo "❌ 'docker compose' 명령을 찾을 수 없습니다. Docker Compose 플러그인을 설치한 뒤 다시 시도하세요."
exit 1
fi
if ! command -v git &> /dev/null; then
echo "❌ git이 설치되어 있지 않습니다. 먼저 설치해주세요 (예: sudo apt install git)."
exit 1
fi
# ── 2. 저장소 받기 ────────────────────────────────────────────
if [ -d "$INSTALL_DIR/.git" ]; then
echo "📦 이미 받아져 있어서 최신 버전으로 갱신합니다."
git -C "$INSTALL_DIR" pull
else
echo "📦 저장소를 내려받는 중..."
git clone "$REPO_URL" "$INSTALL_DIR"
fi
cd "$INSTALL_DIR"
# ── 3. 설정값 입력받기 (curl | bash로 실행돼도 터미널에서 직접 입력받도록 /dev/tty 사용) ──
if [ -f .env ]; then
echo "⚠️ .env가 이미 있어서 기존 설정을 그대로 사용합니다. (다시 설정하려면 .env를 지우고 재실행)"
else
echo ""
read -rp "🌐 이 서버에서 쓸 도메인 (예: attendance.myschool.ac.kr): " SCHOOL_DOMAIN < /dev/tty
read -rp "🔑 교사 회원가입용 인증 코드 (선생님들께 알려줄 코드): " TEACHER_CODE < /dev/tty
if command -v openssl &> /dev/null; then
DB_PW=$(openssl rand -hex 16)
ADMIN_PW=$(openssl rand -hex 8)
else
DB_PW=$(head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n')
ADMIN_PW=$(head -c 16 /dev/urandom | od -An -tx1 | tr -d ' \n')
fi
cat > .env <<EOF
DOMAIN=${SCHOOL_DOMAIN}
DB_PASSWORD=${DB_PW}
TEACHER_SECRET_CODE=${TEACHER_CODE}
ADMIN_RESET_PASSWORD=${ADMIN_PW}
EOF
echo "✅ .env 생성 완료 (DB/관리자 비밀번호는 자동 생성 — 설치 끝나면 화면에 다시 보여드려요)"
fi
# ── 4. firebase-key.json 확인 ─────────────────────────────────
if [ ! -f firebase-key.json ]; then
echo ""
echo "⚠️ firebase-key.json이 없어서 빈 파일로 우선 설치를 진행합니다 (알림 기능은 꺼진 상태로 시작)."
echo " Firebase 콘솔에서 키를 받아 $(pwd)/firebase-key.json으로 덮어쓴 뒤"
echo " 'docker compose restart backend' 하면 알림 기능이 켜집니다."
echo "{}" > firebase-key.json
fi
# ── 5. 실행 (이미지는 새로 빌드하지 않고 미리 만들어둔 이미지를 내려받아 사용) ──
echo ""
echo "🚀 이미지를 내려받고 컨테이너를 실행합니다..."
docker compose pull
docker compose up -d
# shellcheck disable=SC1091
source .env
echo ""
echo "🎉 설치 완료!"
echo "──────────────────────────────────────────"
echo " 도메인: $DOMAIN"
echo " 교사 인증코드: $TEACHER_SECRET_CODE"
echo " DB 비밀번호: $DB_PASSWORD (꼭 기록해두세요)"
echo " 관리자 초기화 비밀번호: $ADMIN_RESET_PASSWORD"
echo "──────────────────────────────────────────"
echo "DNS A레코드를 이 서버의 공인 IP로 연결하면 몇 분 안에 https://$DOMAIN 으로 접속됩니다."
echo "상태 확인: cd $INSTALL_DIR && docker compose logs -f backend"