Автоматизация создания виртуального хоста для web-разработки на базе Apache+Nginx

    Как быстро создать виртуальнй хост и структуру папок одной строкой в терминале


    Так уж сложилось, что для web-разработки я использую отдельный сервер на базе Debian. В первую очередь это обусловлено тем, что я часто работаю вне дома, а так-же это позволяет совместно работать над проектом с коллегами.
    Раньше мне приходилось вручную создавать директории для сайта, копировать и править конфиги. Я тратил на это кучу времени и иногда ошибался, а потом судорожно искал где и что я упуслил.

    Не так давно я задумался над автоматизацией процесса создания виртуальных хостов. Порыв немного в интернетах, и заодно вспомнив bash, родился скрипт, который избавил меня от рутины и ошибок одновременно.

    Конфигурация у меня следующая:
    • Стандартный LAMP + NGINX в качестве фронт-энда.
    • Директория с хостами /var/www/hosting/
    • Директоря виртуального хоста = имени домена
    • Стуктура виртуального хоста
      1. test.ru/cgi-bin
      2. test.ru/www
      3. test.ru/log


    Создаем файл:
    cd ~
    touch addvhost.sh
    chmod +x addvhost.sh
    


    и пишем в него следующее

    #!/bin/sh
    hostmaster="hostmaster@test.ru"      # Электропочта Администратора сервера
    www_path="/var/www/hosting/"        # Путь до директории с виртуальными хостами
    wwwuser="www-data"                
    wwwgroup="www-data"
     
    case "$@" in
        "")
            echo "Введите имя домена (as root)."
            ;;
        *)
            clear
            echo "Создаю директории сайта"
            mkdir -p $www_path$1/www/
            mkdir -p $www_path$1/cgi-bin/
            mkdir -p $www_path$1/log/
            echo "$www_path$1/www/"
            echo "$www_path$1/cgi-bin/"
            echo "$www_path$1/log/"
     
            echo "\nСоздаю пустой index.html "
            echo " " > $www_path$1/www/index.html
            chown -R $wwwuser:$wwwgroup /$www_path$1
            chmod -R 0755 /$www_path$1
            echo "\nДобавляю хост в: /etc/apache2/sites-enabled/$1"
            exec 3>&1 1>/etc/apache2/sites-enabled/$1
            echo "<virtualhost \${HOSTING_HOST}:$2>"
            echo "	ServerName $1"
            echo "	ServerAdmin $hostmaster"
            echo "	"
            echo "	DocumentRoot \${HOSTING_ROOT}/$1/www/"
            echo "	<Directory />"
            echo "		Options Indexes Includes FollowSymLinks MultiViews"
    	echo "		Order allow,deny"
    	echo "		AllowOverride All"
            echo "		Allow from All"
    	echo "	</Directory>"
            echo "	"
    	echo "	<Directory \${HOSTING_ROOT}$1/www/>"
        	echo "		Options Indexes Includes FollowSymLinks MultiViews"
            echo "		Order allow,deny"
        	echo "		AllowOverride All"
        	echo "		Allow from All"
            echo "	</Directory>"
            echo "	"
     	echo "	ScriptAlias /cgi-bin/ \${HOSTING_ROOT}/$1/cgi-bin/"
            echo "	<Directory \${HOSTING_ROOT}/$1/cgi-bin/>"
        	echo "		AllowOverride None"
        	echo "		Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch"
        	echo "		Order allow,deny"
        	echo "		Allow from all"
            echo "	</Directory>"
            echo "	"
        	echo "	ErrorLog \${HOSTING_ROOT}/$1/log/error.log"
      	echo "	LogLevel warn"
        	echo "	CustomLog \${HOSTING_ROOT}/$1/log/access.log combined"
        	echo "	ServerSignature On"
    	echo "	"
            echo "</virtualhost>"
            exec 1>&3
    
            echo "\nДобавляю хост в: /etc/nginx/sites-enabled/$1"
            exec 3>&1 1>/etc/nginx/sites-enabled/$1
            echo "server {"
    	echo "	listen 80;"
    	echo "	server_name $1;"
    	echo "	"
        	echo "	#charset koi8-r;"
          	echo "	"
        	echo "	access_log $www_path$1/log/$1-nginx.access.log main;"
            echo "	"       
        	echo "	location / {"
        	echo "		proxy_pass http://127.0.0.1:$2/;"
        	echo "		proxy_redirect off;"
        	echo "		proxy_set_header Host \$host;"
        	echo "		proxy_set_header X-Real-IP \$remote_addr;"
        	echo "		proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;"
        	echo "		client_max_body_size 40m;"
        	echo "		client_body_buffer_size 256k;"
            echo "		"       			          
        	echo "		proxy_connect_timeout 120;"
        	echo "		proxy_send_timeout 120;"
        	echo "		proxy_read_timeout 120;"
        	echo "		proxy_buffer_size 64k;"
        	echo "		proxy_buffers 4 64k;"
        	echo "		proxy_busy_buffers_size 64k;"
        	echo "		proxy_temp_file_write_size 64k;"
        	echo "		proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;"
        	echo "	}"
        	echo "	#Static files location"
        	echo "	location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|html|flv|mp3)$ "
        	echo "	{"
         	echo "	root $www_path$1/www/;"
        	echo "}"
    		echo "}"
            exec 1>&3
    
            sleep 1
            echo "Перезапуск вэбсервера"
            sudo /etc/init.d/apache2 restart
            sudo /etc/init.d/nginx restart
            echo "Домен создан;)"
            echo "Теперь вы можете перейти по адресу http://$1"
            ;;
    esac
    
    

    Разберемся немного с кодом:

    1. Если Вы решили «скопипастить» скрипт — удалите обратный слэш в "<\/Directory>". Я добавил обратный слэш, дабы редактор не съедал строку.
    2. Я использую frontend/backend технологию, поэтому каждый отдельный хост сидит на отдельном порту апача для проксирования его NGINX-ом.
    Порты должны бвть перечислены в конфиге /etc/apache2/ports.conf

    Listen 8080 
    Listen 8081 
    Listen 8082 
    Listen 8083 
    #И_так_далее
    


    ${HOSTING_HOST} и ${HOSTING_ROOT} — переменные Apache2. Они мне нужны.
    Вместо них вы можете использовать свои переменные или явно указать адреса/пути.
    Так же замечу что ${HOSTING_ROOT} имеет то же значение что и $www_path, поэтому можно использовать и ее.

    Теперь когда мы со всем разобрались — запускаем

    sudo ./addvhost.sh test.ru 8080
    

    где «test.ru» — имя нашего домена (присваивается $1), а «8080» — порт на котором у нас будет сидеть этот тестовый домен (присваивается $2).

    Что имеем в итоге: у нас автоматически создаются директории для виртуальных хостов. Конфиги виртуальных хостов для Apache и Nginx c нужными нам параметрами так-же автоматом генерируются, складываются куда надо и перезапускаются сервисы. Проффит.

    PS. Конечно данный скрипт очень примитивен и не претендует на оригинальность, но все же способен значительно облегчить жизнь начинающему разработчику или администратору.
    Для локальной разработки я использую MAMP Pro. Весь описаный выше функционал, и даже больше, там доступен через красивый и удобный GUI, но не все работает на Mac и не всегда, а жить как-то надо.
    PPS. Как вариант — можно использовать шаблоны конфигурационных файлов вместо echo «каждой строчки». Но мне пока и так нормально.
    Будет время — доработаю и выложу.

    UPD — Новая версия скрипта с использованием шаблонов конфигов доступна здесь
    «Полотенце» из echo заменено на обычный sed -e. Скрипт стал более гибким и простым.

    UPD II — Обновил скрипт и статью. Статью с учетом подсветки кода, а в скрипте порпавил некоторые баги.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 34

      +1
      Спасибо, очень нужная вещь!
        +2
        Вместо кучи echo можно делать так:
        cat > /etc/nginx/sites-enabled/$1 << "EOF"
        blah-blah
        EOF
        
          0
          Доделал вариант с шаблонами. Завтра выложу на всеобщее обозрение, а пока — спать =)
          0
          Не очень понятно, почему при фронтенд/бэкенд для каждого виртхоста нужен отдельный порт?
          У меня на VPS Nginx и апач автоматически конфигурируются панелькой (ISP Manager Lite) автоматически, и все виртуальные хосты имеют общий порт — 8080 (Nginx на 80).
            0
            можно и на один порт посадить, но есть некоторые продукты которые работают только на localhost или привязаны к определенному домену и на других работать не будут (есть и еще более забавные проприоритарные системы). Следовательно мне нужно создать инкубаторские условия для проекта. Мне показалось что такой подход оптимален
            +2
            В сценарий можно еще добавить возможность вставки записи в bind9

            например:

            echo "$1 IN A 127.0.0.1" >> /etc/bind/db.localhost
            /etc/init.d/bind9 restart
              0
              а зачем каждый раз записывать что-то туда, я один раз настрил зону .dev и все=)
              ЗЫ: если есть другие причины, буду рад их послушать.
                0
                Попытаюсь ответить на ваш вопрос.
                Мы не только разрабатываем сайты, но и сопровождаем их. Эти сайты в свою очередь могут работать на другой CMS bkb вовсе на каком-то самописном движке.

                Яркий пример — ABO.CMS. Работает только на домене, к которому привязана лицензия. Следовательно в зоне .dev сработает редирект на сайт разработчика на страницу о нарушении лицензии.
                По понятным причинам, мы не будем проводить работы на «боевом» сайте. Мы делаем копию сайта и базы и потом начинаем уже его дорабатывать/перерабатывать и т.д. И здесь нас выручает создание клона зоны на локальном сервере, а уже потом мы можем данный хост проксировать nginx-ом куда угодно.
                  0
                  а если зделать декод и отключить проверку лиценции?=)
                    0
                    Нет, этим мы точно заниматься не будем. Во первых это лишние трудозатраты, а во вторых нарушение закона.
              +1
              использую в этих целях хостинг панель ISPConfig
              установка на дебиан или убунту дело менее чем пары часов.

              мануалы по установке на howtoforge

              вот например документ прикручивания NGINX
              www.howtoforge.com/nginx-catch-all-host-as-front-end-to-apache-for-ispconfig-3-on-debian-lenny
                0
                Смотрел в сторону этого продукта, но мне он не подошел по некоторым соображениям. Хотелось иметь возможность добавлять и удалять виртуальные хосты одной строчкой в консоли. Например одна из необходимых мне задачь — не имея помпьютера под рукой создать виртуальный хост. Решение — захожу SSH клиентом на сервер со своего коммуникатора и пишу строчку и не переживаю.

                Вообще можно еще много чего наворотить и решений для автоматизации хостинга море, но вот таких вот простых решений, ориентированых на разработчиков, а не ентерпрайз сектор — я не встречал.
                0
                Архив с новой версией — пустой.
                  +1
                  Прошу прощения. Файл перезалил.
                    +1
                    Спасибо за проделанную работу!
                  0
                  а у меня создание хоста ручками занимает меньше минуты, я засекал=)
                    0
                    c данным скриптом — менее 10 сек. =)
                      0
                      экономия — 50 секунд жизни=)
                    0
                    Единственное что я еще не победил — это корректное добавлене записи в /etc/apache2/ports.conf

                    в идеале хочется, писать строку «avhst test.ru». Скрипт бы залазил в ports.conf, смотрел последний добавленый порт, прибавлял бы к нему единичку и передавал в качестве значения для "$2".
                    Если у кого есть «железные» мысли — делитесь.

                    пытался делать tail последней строки, но через раз индеец выдает ошибку, ругаясь на неверный номер порта.
                      0
                      Можешь пояснить подробнее, если честно я не в курил.
                      bash это же не сложно, иногда только буквы лишние писать приходится.
                        0
                        не понял сути вопроса
                        Что же касается описанного функционала — тестируется
                      +1
                      Можно сократить конструкцию
                      mkdir -p $www_path$1/www/
                      mkdir -p $www_path$1/cgi-bin/
                      mkdir -p $www_path$1/log/

                      до

                      mkdir -p $www_path$1/{www,cgi-bin,log}
                        0
                        Спасибо за мысль.
                          0
                          Также луче слушать не все интерфейсы Listen 8080, а только локалхост Listen 127.0.0.1:8080

                        0
                        зашел посмотреть новую версию через IE 8, а меня перекинуло на unsp.sliderweb.ru/ и попросили обновиться до IE8 ) парадокс
                          0
                          хм — только что проверил из под ослика восьмого — все отлично
                            0
                            «Не поддерживаемая версия браузера» для Mozilla 6.0 … 8(
                          0
                          а как же?

                          location ~ /\.htaccess {
                          deny all;
                          }
                            0
                            а зачем мне это?
                            0
                            по поводу вот этой строчки
                            echo " location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|html|flv|mp3)$ "

                            тут уже замечали, что такое не айс делать — при динамическом формировании контента может выйти бяка, но замену я както не вкурил (
                              0
                              в данном случае это не критично. На худой конец шаблоны можно поправить и вовсе отключить сей локейшен.
                              0
                              Как то много букв. Как не странно у меня тоже такая задача была и как не странно я очень ленивый :)
                              У меня на FreeBSD куча скриптов, включая создание хостов. (мой вариант 28 строк с комментариями)

                              В выходной выложу статейку :) со скриптами, надеюсь пригодится.
                                0
                                и эти много букв работают и упрощают жизнь. Как сумел — так решил
                                  0
                                  все, хорошо. Зачет:)

                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                              Самое читаемое