Развёртывание нескольких виртуальных хостов на Ubuntu 22.04 с помощью Terraform
В этой статье показано, как настроить два name-based виртуальных хоста на Ubuntu 22.04 с Apache, автоматизировав развёртывание EC2-инстанса и конфигурации с помощью Terraform и userdata-скрипта. Приведены готовые файлы, пошаговые команды, рекомендации по безопасности и проверочные сценарии.
Краткое введение

Виртуальный хостинг позволяет запускать несколько веб-сайтов на одном сервере. Существует два основных подхода:
- IP-based — каждый сайт привязан к отдельному IP-адресу.
- Name-based — несколько имён привязаны к одному IP; выбор сайта производится по Host-заголовку HTTP.
Terraform — инструмент инфраструктуры как кода (IaC) от HashiCorp. Он описывает желаемое состояние ресурсов (EC2, security group и т. п.) и синхронизирует реальное окружение с этой конфигурацией, изменяя только необходимые части.
Что рассмотрим
- Как автоматизировать развёртывание Ubuntu 22.04 + Apache на EC2 с помощью Terraform.
- Как сконфигурировать два name-based виртуальных хоста (vhost1 и vhost2).
- Как протестировать и отладить настройку.
Требования перед началом
- Базовые знания Terraform.
- Установленный Terraform на вашей локальной машине.
- Настроенный AWS-профиль (ключи/профили) на локальной машине.
- Понимание принципов настройки виртуальных хостов в Apache.
Важно: в учебной лаборатории домены www.vhost1.com и www.vhost2.com добавлены в /etc/hosts на инстансе как 127.0.0.1, чтобы демонстрация работала без публичных DNS-записей.
Структура проекта и ключевые файлы
Проект разделён на несколько файлов для прозрачности и простоты ревью:
- userdata.sh — bash-скрипт, который устанавливает Apache, создаёт каталоги для сайтов, копирует конфигурацию виртуальных хостов и включает их.
- sec-grp.tf — ресурс AWS security group с правилами входящего и исходящего трафика.
- vhost-template.conf — конфигурация Apache для двух виртуальных хостов (vhost1 и vhost2).
- main.tf — провайдер, EC2-инстанс, provisioner (загрузка файла) и вывод public_dns.

Ниже — пошаговые команды и содержимое файлов. Код-блоки оставлены без изменений, чтобы их можно было копировать напрямую.
Шаг 1. Создаём рабочую директорию
$ mkdir virtual-hosts-terraformСоздайте каталог и поместите туда все файлы проекта.
Шаг 2. userdata.sh — автоматизация настройки сервера
Откройте файл:
$ vi userdata.shСодержимое userdata.sh:
#!/bin/bash
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install apache2 -y
sudo systemctl restart apache2
sudo sh -c "echo 127.0.0.1 www.vhost1.com >> /etc/hosts"
sudo sh -c "echo 127.0.0.1 www.vhost2.com >> /etc/hosts"
sudo mkdir -p /var/www/vhost_1/public_html
sudo mkdir -p /var/www/vhost_2/public_html
sudo chown -R $USER:$USER /var/www/vhost_1/public_html
sudo chown -R $USER:$USER /var/www/vhost_2/public_html
sudo chmod -R 755 /var/www
sudo echo "Webpage from: Virtual Host 1." > /var/www/vhost_1/public_html/index.html
sudo echo "Webpage from: Virtual Host 2." > /var/www/vhost_2/public_html/index.html
sudo cp /home/ubuntu/vhosts.conf /etc/apache2/sites-available/vhosts.conf
sudo a2ensite vhosts.conf
sudo a2dissite 000-default.conf
sudo systemctl restart apache2Короткое пояснение к userdata.sh:
- Обновляет систему и устанавливает Apache.
- Добавляет записи в /etc/hosts для локального тестирования имён.
- Создаёт каталоги сайтов и права доступа.
- Записывает простые index.html для каждого vhost.
- Копирует сгенерированную конфигурацию виртуальных хостов и включает её.
Совет: не храните секретные ключи в userdata. В userdata можно указывать минимальный набор команд по настройке.
Шаг 3. sec-grp.tf — правила доступа
Создайте файл:
$ vi sec-grp.tfСодержимое sec-grp.tf:
resource "aws_security_group" "ec2-sg" {
name = "ec2-grp"
description = "Set Ingress and Egress Rules "
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}Примечание по безопасности: правило SSH (22) открыто для всех (0.0.0.0/0). В продакшне ограничьте доступ по IP или используйте VPN/Session Manager.
Шаг 4. vhost-template.conf — конфигурация Apache
Создайте файл:
$ vi vhost-template.confСодержимое vhost-template.conf:
ServerAdmin [email protected]
ServerName vhost1
ServerAlias www.vhost1.com
DocumentRoot /var/www/vhost_1/public_html
ErrorLog ${APACHE_LOG_DIR}/error.log
ServerAdmin [email protected]
ServerName vhost2
ServerAlias www.vhost2.com
DocumentRoot /var/www/vhost_2/public_html
ErrorLog ${APACHE_LOG_DIR}/error.log
Пояснение: каждая секция
Шаг 5. main.tf — провайдер и инстанс
Создайте файл:
$ vi main.tfСодержимое main.tf:
provider "aws" {
region ="us-east-1"
}
resource "aws_instance" "webserver" {
ami ="ami-09d56f8956ab235b3"
instance_type = "t2.micro"
key_name = "Name-of-EC2-Key-Pair"
vpc_security_group_ids = [aws_security_group.demo-sg.id]
associate_public_ip_address = true
provisioner "file" {
source = "vhost-template.conf"
destination = "/home/ubuntu/vhosts.conf"
connection {
type = "ssh"
user = "ubuntu"
private_key = "${file("/Path/to/EC2-Key-Pair")}"
host = "${self.public_dns}"
}
}
user_data = "${file("userdata.sh")}"
tags = {
Name = "VirtualHostTutorial"
}
}
output "IPAddress" {
value = "${aws_instance.webserver.public_dns}"
}Что важно проверить в main.tf:
- Убедитесь, что имя security group соответствует вашей конфигурации (aws_security_group.demo-sg.id в примере — может отличаться).
- Не храните приватные ключи в репозитории; используйте локальные пути или секретные менеджеры.
- AMI и region должны быть актуальны для вашего аккаунта и региона.
Примечание: provisioner “file” загружает vhost-template.conf на инстанс. user_data выполняет скрипт userdata.sh.

Шаг 6. Инициализация и применение Terraform
Инициализируйте проект и примените конфигурацию:
$ terraform init$ terraform apply
После успешного выполнения вы увидите сообщение о завершении развёртывания.

Тестирование настройки
Подключитесь по SSH или используйте curl напрямую с машины (если вы добавили записи в локальный /etc/hosts):
$ curl www.vhost1.comОжидаемый отклик: строка из /var/www/vhost_1/public_html/index.html — “Webpage from: Virtual Host 1.”.
$ curl www.vhost2.comОжидаемый отклик: строка “Webpage from: Virtual Host 2.”.

Отладка и распространённые проблемы
- Apache не отвечает: проверьте статус службы
sudo systemctl status apache2- Ошибки в конфигурации виртуальных хостов: проверьте синтаксис Apache
sudo apache2ctl configtest- Логи ошибок
sudo tail -n 100 /var/log/apache2/error.log/etc/hosts не содержит записей: убедитесь, что userdata корректно добавил строки и что вы проверяете на той же машине.
Security group блокирует доступ: проверьте aws console или terraform show, что порты 80/22 открыты в нужных CIDR.
SSH-подключение не удаётся: проверьте key_name и private_key в main.tf; убедитесь, что приватный ключ доступен и имеет корректные права (chmod 600).
Рекомендации по безопасности и эксплуатации
- Ограничьте SSH-доступ по IP или используйте AWS Systems Manager Session Manager вместо SSH.
- Используйте IAM-роли и минимальные привилегии для сервисов.
- Не храните приватные ключи в коде/репозитории. Вместо этого используйте локальные пути, переменные окружения или секретные хранилища.
- Для SSL/TLS используйте Let’s Encrypt + Certbot или AWS Certificate Manager (если через ALB).
- Автоматизируйте обновления и мониторинг (os-updates, fail2ban, CloudWatch).
Сценарии приёмки и тестовые кейсы
- Инстанс успешно создан и имеет public_dns.
- Apache запущен и конфигурация виртуальных хостов включена (a2ensite vhosts.conf).
- curl www.vhost1.com возвращает ожидаемую строку.
- curl www.vhost2.com возвращает ожидаемую строку.
- Порты 80 и 22 доступны из разрешённых подсетей согласно security group.
Критерии приёмки
- Все пункты тестовых кейсов выполнены без ручной правки файлов на инстансе.
Альтернативные подходы
- Использовать Terraform вместе с cloud-init вместо userdata для более гибкой настройки; cloud-init умеет работать с cloud-config и модулями.
- Вместо provisioner’ов использовать образ AMI с предустановленным Apache (Immutable Infra).
- Для масштабируемости разместить веб-приложения за балансировщиком нагрузки (ALB) и обслуживать vhost’ы через путь/host-based routing.
Чек-листы по ролям
DevOps:
- Убедиться в idempotence Terraform-конфигов.
- Автоматизировать CI для terraform plan/apply в защищённой среде.
Системный администратор:
- Настроить ротацию сертификатов и обновления системы.
- Проверять логи и доступность сервисов.
Инженер безопасности:
- Проверить правила security group и доступ по SSH.
- Настроить аудит доступа к ключам и использовать KMS/Secrets Manager.
Короткий глоссарий
- Terraform — IaC-инструмент для описания инфраструктуры.
- HCL — язык конфигурации HashiCorp.
- userdata — скрипт, который выполняется при первом старте инстанса.
- provisioner — механизм Terraform для выполнения действий на ресурсах (например, копирования файлов).
- VirtualHost — настройка Apache для обслуживания нескольких сайтов на одном инстансе.
Краткое резюме
Мы создали рабочий пример развертывания двух name-based виртуальных хостов на Ubuntu 22.04 с Apache, полностью автоматизировав процесс с помощью Terraform и userdata. В статье приведены все файлы, проверочные команды и рекомендации по безопасности.
Важно: в реальных окружениях избегайте широкого открытия SSH и хранения секретов в коде. Используйте IAM, SSM и безопасные практики управления ключами.
Заключение
Попробуйте скопировать приведённые файлы в свою директорию, адаптировать их под ваш AWS-аккаунт и запустить terraform init && terraform apply. Это даст наглядное понимание, как Terraform взаимодействует с ресурсами и как можно автоматизировать конфигурацию виртуальных хостов.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента