기본 콘텐츠로 건너뛰기

리눅스 웹 서버 환경 자동 구축: Tomcat, PHP, MariaDB, SVN 셋업 스크립트

DEVOPS / AUTOMATION

리눅스 웹 서버 환경 자동 구축: Tomcat, PHP, MariaDB, SVN 셋업 스크립트

신규 웹 서비스 런칭 시 반복되는 리눅스 계정 생성, Tomcat/PHP 설정, DB 및 SVN 구축 작업을 Bash 스크립트 하나로 자동화하는 방법을 공유합니다. 인프라 세팅 시간을 단축하고 휴먼 에러를 방지하는 실무 예제를 확인해 보세요.

1. 스크립트 기능 및 자동화 워크플로우

웹 서비스를 위한 인프라를 구축할 때, 단순히 사용자 계정만 만드는 것이 아니라 웹 서버(Apache/Tomcat), 데이터베이스(MariaDB), 버전 관리(SVN)까지 유기적으로 연결해야 합니다. 이 스크립트는 복잡한 과정을 순차적으로 자동 수행합니다.

  • OS 사용자 관리: 리눅스 계정 생성(useradd) 및 비밀번호 설정
  • 웹/앱 서버 구성 (언어 선택):
    • JAVA 선택 시: Tomcat 인스턴스 생성, server.xml 개별 설정, Apache mod_jk 연동(VirtualHost, workers.properties) 자동화
    • PHP 선택 시: Apache VirtualHost 설정 및 phpinfo() 테스트 페이지 생성
  • 버전 관리 시스템: SVN 저장소(Repo) 생성 및 권한 설정 (선택 사항)
  • 데이터베이스: MariaDB 계정/DB 생성 및 GRANT 권한 부여 (선택 사항)
  • 서비스 재시작: 설정 적용을 위한 Apache 재시작 및 신규 계정 전환

2. 전체 자동화 스크립트 (Bash Source)

아래 코드를 user_add.sh 등의 이름으로 저장하여 사용합니다. 이 스크립트는 CentOS/RHEL 계열의 경로 설정(/etc/httpd, /usr/share/tomcat7 등)을 기준으로 작성되었습니다.

#!/bin/bash

clear

echo ==================================================================
echo "                      UserAdd Process Start                        "
echo ==================================================================

echo -n "User Name : "
read username

useradd "$username"

echo ------------------------
echo "PassWord Setting"
echo ------------------------
passwd "$username"

echo "User Add Success!!!"

echo ==================================================================
echo "      Tomcat User Add OR PHP CONFIG & VirtualHost config making      "
echo ==================================================================

existCheck=$(grep -n "#SERVICE $username CONFIG START" /etc/httpd/conf/VirtualHost.conf | cut -d: -f1 | head -1)

function fn_tomcatConfigration(){
  echo "Tomcat User Add.."
  echo "****************************************************************"
  cat /etc/httpd/conf/port_list
  echo "****************************************************************"
  echo -n "add New AJP Port : "
  read ajpport
  echo -n "add New Shutdown Port : "
  read shutdownport
  echo -n "add New Redirect Port : "
  read redirectport

  echo "SERVICE : $username / AJP_PORT : $ajpport / SHUTDOWN_PORT : $shutdownport / REDIRECT_PORT : $redirectport" >> /etc/httpd/conf/port_list

  echo "#SERVICE $username CONFIG START" >> /etc/httpd/conf/workers.properties
  echo "#AJP port : $ajpport" >> /etc/httpd/conf/workers.properties
  echo "#Shutdown port : $shutdownport" >> /etc/httpd/conf/workers.properties
  echo "#Redirect port : $redirectport" >> /etc/httpd/conf/workers.properties
  echo "worker.list = $username" >> /etc/httpd/conf/workers.properties
  echo "worker.$username.type=ajp13" >> /etc/httpd/conf/workers.properties
  echo "worker.$username.host=localhost" >> /etc/httpd/conf/workers.properties
  echo "worker.$username.port=$ajpport" >> /etc/httpd/conf/workers.properties
  echo "worker.$username.lbfactor=1" >> /etc/httpd/conf/workers.properties
  echo "#SERVICE $username CONFIG END" >> /etc/httpd/conf/workers.properties

  echo "#SERVICE $username CONFIG START" >> /etc/httpd/conf/VirtualHost.conf
  echo "#AJP port : $ajpport" >> /etc/httpd/conf/VirtualHost.conf
  echo "#Shutdown port : $shutdownport" >> /etc/httpd/conf/VirtualHost.conf
  echo "#Redirect port : $redirectport" >> /etc/httpd/conf/VirtualHost.conf
  echo "<VirtualHost *:80>" >> /etc/httpd/conf/VirtualHost.conf
  echo "DocumentRoot /home/$username/webapps/ROOT" >> /etc/httpd/conf/VirtualHost.conf
  # 도메인은 실제 환경에 맞게 수정 필요
  echo "ServerName $username.ubncorp.co.kr" >> /etc/httpd/conf/VirtualHost.conf
  echo "ServerAlias $username.ubncorp.co.kr" >> /etc/httpd/conf/VirtualHost.conf
  echo "ErrorLog /var/log/httpd/$username-error_log" >> /etc/httpd/conf/VirtualHost.conf
  echo "CustomLog /var/log/httpd/$username-access_log combiend" >> /etc/httpd/conf/VirtualHost.conf
  echo "" >> /etc/httpd/conf/VirtualHost.conf
  echo "JkMount /* $username" >> /etc/httpd/conf/VirtualHost.conf
  # 정적 파일 처리를 위한 제외 설정
  echo "JkUnMount /*.gif ajp13" >> /etc/httpd/conf/VirtualHost.conf
  echo "JkUnMount /*.jpg ajp13" >> /etc/httpd/conf/VirtualHost.conf
  echo "JkUnMount /*.jpeg ajp13" >> /etc/httpd/conf/VirtualHost.conf
  echo "JkUnMount /*.bmp ajp13" >> /etc/httpd/conf/VirtualHost.conf
  echo "JkUnMount /*.png ajp13" >> /etc/httpd/conf/VirtualHost.conf
  echo "JkUnMount /*.htm ajp13" >> /etc/httpd/conf/VirtualHost.conf
  echo "JkUnMount /*.html ajp13" >> /etc/httpd/conf/VirtualHost.conf
  echo "</VirtualHost>" >> /etc/httpd/conf/VirtualHost.conf
  echo "#SERVICE $username CONFIG END" >> /etc/httpd/conf/VirtualHost.conf

  # Tomcat 개별 server.xml 생성
  echo "<?xml version='1.0' encoding='utf-8'?>" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "<Server port='$shutdownport' shutdown='SHUTDOWN'>" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo " <Listener className='org.apache.catalina.core.AprLifecycleListener' SSLEngine='on' />" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo " <Listener className='org.apache.catalina.core.JasperListener' />" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo " <Listener className='org.apache.catalina.core.JreMemoryLeakPreventionListener' />" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo " <Listener className='org.apache.catalina.mbeans.GlobalResourcesLifecycleListener' />" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo " <Listener className='org.apache.catalina.core.ThreadLocalLeakPreventionListener' />" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo " <Service name='Catalina'>" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "   <Connector port='$ajpport' protocol='AJP/1.3' redirectPort='$redirectport' URIEncoding='UTF-8' />" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "   <Engine name='Catalina' defaultHost='$username.ubncorp.co.kr'>" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "     <Host name='$username.ubncorp.co.kr' appBase='/home/$username/webapps' unpackWARs='true' autoDeploy='true' xmlValidation='false' xmlNamespaceAware='false'>" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "       <Alias>$username.ubncorp.co.kr</Alias>" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "       <Valve className='org.apache.catalina.valves.AccessLogValve' directory='/home/$username/logs'" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "              prefix='$username.ubncorp.co.kr_access_log.' suffix='.txt'" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "              pattern='%h %l %u %t "%r" %s %b' />" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "     </Host>" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "   </Engine>" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo " </Service>" >> /usr/share/tomcat7/virtualhost/$username-server.xml
  echo "</Server>" >> /usr/share/tomcat7/virtualhost/$username-server.xml

  SERVERS_HOME=/home
  SERVER_NAME=$username
  SERVER_PATH="$SERVERS_HOME/$username"
  TOMCAT_HOME=/usr/share/tomcat7

  echo "new tomcat will create in $SERVER_PATH ....."
  mkdir "$SERVER_PATH/logs"
  cp -Rf "$TOMCAT_HOME/webapps" "$SERVER_PATH/webapps"
  cp -Rf "$TOMCAT_HOME/conf" "$SERVER_PATH/conf"
  chown -R "$username:$username" "$SERVER_PATH"
  chmod -R 755 "$SERVER_PATH"

  # 불필요한 기본 앱 삭제
  echo "webapps subdirectory deleted..."
  rm -rf /home/$username/webapps/manager
  rm -rf /home/$username/webapps/host-manager
  rm -rf /home/$username/webapps/examples
  rm -rf /home/$username/webapps/docs
  rm -rf /home/$username/webapps/ROOT

  echo "Tomcat User Add Success!!!"
}

function fn_removeTomcatConfig(){
  rm -f /usr/share/tomcat7/virtualhost/$username-server.xml
  rm -rf /home/$username/*
  mv /etc/httpd/conf/port_list /etc/httpd/conf/port_list.tmp

  while read line1;
  do
    if [[ $line1 != *"$username"* ]]; then
      echo "$line1" >> /etc/httpd/conf/port_list
    fi
  done < /etc/httpd/conf/port_list.tmp
  rm -f /etc/httpd/conf/port_list.tmp

  sed -i "/#SERVICE $username CONFIG START/,/#SERVICE $username CONFIG END/d" /etc/httpd/conf/VirtualHost.conf
  sed -i "/#SERVICE $username CONFIG START/,/#SERVICE $username CONFIG END/d" /etc/httpd/conf/workers.properties

  echo "delete user from config is complete..."
  echo "**************************************************************"
  echo "   workers.properties AND VirtualHost.conf REMOVE COMPLETE!!!  "
  echo "**************************************************************"
}

function fn_overwirteTomcatConfig(){
  if [ "$existCheck" ]; then
    echo -n "user exist! overwrite user? (Y/N) : "
    read overwrite_yn
    if [ "$overwrite_yn" == "Y" ]; then
      fn_removeTomcatConfig
      fn_tomcatConfigration
    elif [ "$overwrite_yn" == "N" ]; then
      echo "tomcat configration pass!!!"
    else
      echo "Please check the input value.. (overwrite Y/N)"
      fn_overwirteTomcatConfig
    fi
  else
    fn_tomcatConfigration
  fi
}

function fn_phpConfig(){

  echo "PHP VirtualHost setting..."
  echo "/home/$username/public_html"

  mkdir -p /home/$username/public_html

  echo "#SERVICE $username CONFIG START" >> /etc/httpd/conf/VirtualHost.conf
  echo "#support PHP config.." >> /etc/httpd/conf/VirtualHost.conf
  echo "<VirtualHost *:80>" >> /etc/httpd/conf/VirtualHost.conf
  echo "  DocumentRoot /home/$username/public_html" >> /etc/httpd/conf/VirtualHost.conf
  echo "  ServerName $username.ubncorp.co.kr" >> /etc/httpd/conf/VirtualHost.conf
  echo "  ServerAlias $username.ubncorp.co.kr" >> /etc/httpd/conf/VirtualHost.conf
  echo "  ErrorLog /home/$username/log/$username-error_log" >> /etc/httpd/conf/VirtualHost.conf
  echo "  CustomLog /home/$username/log/$username-access_log combiend" >> /etc/httpd/conf/VirtualHost.conf
  echo "</VirtualHost>" >> /etc/httpd/conf/VirtualHost.conf
  echo "#SERVICE $username CONFIG END" >> /etc/httpd/conf/VirtualHost.conf

  echo "/home/$username/public_html"
  mkdir -p /home/$username/log

  chmod 775 /home/$username
  chmod 775 /home/$username/public_html
  chmod 775 /home/$username/log

  chown $username.$username /home/$username/public_html
  chown $username.$username /home/$username/log

  echo " " >> /home/$username/public_html/index.php
  echo "<? phpinfo(); ?>" >> /home/$username/public_html/index.php

  chown $username.$username /home/$username/public_html/index.php
  chmod 775 /home/$username/public_html/index.php

  echo "checking -----------------------------------------------------------"
  ls -al /home/$username
  echo "checking -----------------------------------------------------------"
  ls -al /home/$username/public_html
}

function fn_overwirtePHPConfig(){
  if [ "$existCheck" ]; then
    echo -n "user exist! overwrite user? (Y/N) : "
    read overwrite_yn1
    if [ "$overwrite_yn1" == "Y" ]; then
      fn_removeTomcatConfig
      fn_phpConfig
    elif [ "$overwrite_yn1" == "N" ]; then
      echo "PHP configration pass!!!"
    else
      echo "Please check the input value.. (overwrite Y/N)"
      fn_overwirtePHPConfig
    fi
  else
    fn_phpConfig
  fi
}

function fn_selectLanguage(){
  echo -n "select Development Language....... (PHP/JAVA) : "
  read language
  if [ "$language" == "JAVA" ]; then
    fn_overwirteTomcatConfig
  elif [ "$language" == "PHP" ]; then
    fn_overwirtePHPConfig
  else
    echo "Please check the input value.. (Supported language : PHP / JAVA)"
    fn_selectLanguage
  fi
}

fn_selectLanguage

echo ==================================================================
echo "                          SVN Create                          "
echo ==================================================================

function fn_createSvn(){
  echo -n "create SVN repo? (Y/N) : "
  read create_svn_yn
  if [ "$create_svn_yn" == "Y" ]; then
    svnadmin create --fs-type fsfs /repos/$username
    ls -l /repos
    mv /repos/$username/conf/svnserve.conf /repos/$username/conf/svnserve.conf.old
    echo "[general]" >> /repos/$username/conf/svnserve.conf
    echo "anon-access = none" >> /repos/$username/conf/svnserve.conf
    echo "auth-access = write" >> /repos/$username/conf/svnserve.conf
    echo "password-db = passwd" >> /repos/$username/conf/svnserve.conf
    echo "authz-db = authz" >> /repos/$username/conf/svnserve.conf
    cat /repos/$username/conf/svnserve.conf
    echo "SVN Create Success!!!"
  elif [ "$create_svn_yn" == "N" ]; then
    echo "SVN Create PASS!!!"
  else
    echo "Please check the input value.. (create SVN repo : Y/N)"
    fn_createSvn
  fi
}

fn_createSvn

echo ==================================================================
echo "              MariaDB Create Database & useradd                   "
echo ==================================================================

function fn_createMariaDB(){
  echo -n "create MariaDB user and database? (Y/N) : "
  read create_db_yn
  if [ "$create_db_yn" == "Y" ]; then
    echo "Username : $username"
    echo "dbname   : $username"
    echo -n "User p/w : "
    read userpw

    # 임시 SQL 파일 생성
    echo " " >> mysql_useradd.sql
    echo "use mysql;" >> mysql_useradd.sql
    echo "create database $username default character set utf8 COLLATE utf8_general_ci;" >> mysql_useradd.sql
    echo "insert into user (host, user, password) values ('localhost', '$username', password('$userpw'));" >> mysql_useradd.sql
    echo "GRANT ALL PRIVILEGES ON $username.* TO '$username'@'%' IDENTIFIED BY '$userpw' with GRANT OPTION;" >> mysql_useradd.sql
    echo "FLUSH PRIVILEGES;" >> mysql_useradd.sql

    # 주의: -p 옵션 뒤에 패스워드 공백 없이 입력 (보안 주의)
    mysql -u root -ptft105 < ./mysql_useradd.sql
    cat ./mysql_useradd.sql
    rm -rf ./mysql_useradd.sql

    echo "MariaDB Create Success!!!"
  elif [ "$create_db_yn" == "N" ]; then
    echo "MariaDB Create PASS!!!"
  else
    echo "Please check the input value.. (create MariaDB user and database : Y/N)"
    fn_createMariaDB
  fi
}

fn_createMariaDB

echo ==================================================================
echo "                                END                               "
echo ==================================================================

service httpd restart
cd /home/$username
su "$username"

3. 사용 방법 및 실행 가이드

  1. 스크립트 작성: 위 코드를 복사하여 /root/user_add.sh 파일을 생성합니다.
  2. 실행 권한 부여: chmod +x /root/user_add.sh 명령어로 실행 권한을 줍니다.
  3. 스크립트 실행: Root 권한으로 ./user_add.sh를 실행합니다.
  4. 정보 입력: 프롬프트 안내에 따라 아래 정보를 순서대로 입력합니다.
    • 사용자명 (User Name)
    • 개발 언어 선택 (PHP / JAVA)
    • (JAVA 선택 시) AJP, Shutdown, Redirect 포트 번호
    • SVN 저장소 생성 여부 (Y/N)
    • MariaDB 생성 여부 (Y/N) 및 DB 비밀번호
💡 Tip: 스크립트는 Apache(httpd)와 Tomcat이 AJP 프로토콜(mod_jk)로 연동되는 구조를 가정합니다. 아래 아키텍처 다이어그램을 참고하여 포트 충돌이 없도록 설정해야 합니다.

4. 운영 환경 적용 시 주의사항 (Customizing)

이 스크립트는 실무 예제이므로, 실제 운영 서버에 적용하기 전에 반드시 자신의 환경에 맞게 수정해야 합니다. 다음 항목들을 체크하세요.

  • 보안 민감 정보 수정: 스크립트 내 하드코딩된 MariaDB Root 패스워드(-ptft105)와 도메인 주소(ubncorp.co.kr)는 반드시 변경해야 합니다.
  • 디렉터리 경로 확인: /etc/httpd/conf/, /usr/share/tomcat7, /repos 등의 경로가 실제 서버 구조와 일치하는지 확인하세요.
  • 예외 처리 강화: 포트 충돌, 이미 존재하는 사용자명, DB 중복 생성 시의 에러 핸들링 로직을 추가하면 더욱 안정적으로 사용할 수 있습니다.

댓글

이 블로그의 인기 게시물

Java Servlet Request Parameter 완전 정복 — GET/POST 모든 파라미터 확인 & 디버깅 예제 (Request Parameter 전체보기)

Java Servlet Request Parameter 완전 정복 — GET/POST 모든 파라미터 확인 & 디버깅 예제 Java Servlet Request Parameter 완전 정복 웹 애플리케이션에서 클라이언트로부터 전달되는 Request Parameter 를 확인하는 것은 필수입니다. 이 글에서는 Java Servlet 과 JSP 에서 GET/POST 요청 파라미터를 전체 출력하고 디버깅하는 방법을 다양한 예제와 함께 소개합니다. 1. 기본 예제: getParameterNames() 사용 Enumeration<String> params = request.getParameterNames(); System.out.println("----------------------------"); while (params.hasMoreElements()){ String name = params.nextElement(); System.out.println(name + " : " + request.getParameter(name)); } System.out.println("----------------------------"); 위 코드는 요청에 포함된 모든 파라미터 이름과 값을 출력하는 기본 방법입니다. 2. HTML Form과 연동 예제 <form action="CheckParamsServlet" method="post"> 이름: <input type="text" name="username"><br> 이메일: <input type="email" name="email"><b...

PostgreSQL 달력(일별,월별)

SQL 팁: GENERATE_SERIES로 일별, 월별 날짜 목록 만들기 SQL 팁: GENERATE_SERIES 로 일별, 월별 날짜 목록 만들기 데이터베이스에서 통계 리포트를 작성하거나 비어있는 날짜 데이터를 채워야 할 때, 특정 기간의 날짜 목록이 필요할 수 있습니다. PostgreSQL과 같은 데이터베이스에서는 GENERATE_SERIES 함수를 사용하여 이 작업을 매우 간단하게 처리할 수 있습니다. 1. 🗓️ 일별 날짜 목록 생성하기 2020년 1월 1일부터 12월 31일까지의 모든 날짜를 '1 day' 간격으로 생성하는 쿼리입니다. WITH date_series AS ( SELECT DATE(GENERATE_SERIES( TO_DATE('2020-01-01', 'YYYY-MM-DD'), TO_DATE('2020-12-31', 'YYYY-MM-DD'), '1 day' )) AS DATE ) SELECT DATE FROM date_series 이 쿼리는 WITH 절(CTE)을 사용하여 date_series 라는 임시 테이블을 만들고, GENERATE_SERIES 함수로 날짜를 채웁니다. 결과 (일별 출력) 2. 📅 월별 날짜 목록 생성하기 동일한 원리로, 간격을 '1 MONTH' 로 변경하면 월별 목록을 생성할 수 있습니다. TO...

CSS로 레이어 팝업 화면 가운데 정렬하는 방법 (top·left·transform 완전 정리)

레이어 팝업 센터 정렬, 이 코드만 알면 끝 (CSS 예제 포함) 이벤트 배너나 공지사항을 띄울 때 레이어 팝업(center 정렬) 을 깔끔하게 잡는 게 생각보다 어렵습니다. 화면 크기가 변해도 가운데에 고정되고, 모바일에서도 자연스럽게 보이게 하려면 position , top , left , transform 을 정확하게 이해해야 합니다. 이 글에서는 아래 내용을 예제로 정리합니다. 레이어 팝업(center 정렬)의 기본 개념 자주 사용하는 position: absolute / fixed 정렬 방식 질문에서 주신 스타일 top: 3.25%; left: 50%; transform: translateX(-50%) 의 의미 실무에서 바로 쓰는 반응형 레이어 팝업 HTML/CSS 예제 1. 레이어 팝업(center 정렬)이란? 레이어 팝업(레이어 팝업창) 은 새 창을 띄우는 것이 아니라, 현재 페이지 위에 div 레이어를 띄워서 공지사항, 광고, 이벤트 등을 보여주는 방식을 말합니다. 검색엔진(SEO) 입장에서도 같은 페이지 안에 HTML이 존재 하기 때문에 팝업 안의 텍스트도 정상적으로 인덱싱될 수 있습니다. 즉, “레이어 팝업 센터 정렬”, “레이어 팝업 만드는 방법”과 같이 관련 키워드를 적절히 넣어주면 검색 노출에 도움이 됩니다. 2. 질문에서 주신 레이어 팝업 스타일 분석 질문에서 주신 스타일은 다음과 같습니다. <div class="layer-popup" style="width:1210px; z-index:9001; position:absolute; top:3.25%; left:50%; transform:translateX(-50%);"> 레이어 팝업 내용 <...