VM アプリケーションスクリプト
VM 作成時に cloud-init または CustomScriptExtension で実行するアプリケーション初期化スクリプト集。
目次
使用方法
cloud-init (Linux)
// Bicep で cloud-init を使用
module vm 'br/public:avm/res/compute/virtual-machine:0.21.0' = {
params: {
customData: loadFileAsBase64('scripts/vm-init/squid-init.yaml')
}
}CustomScriptExtension (Linux/Windows)
module vm 'br/public:avm/res/compute/virtual-machine:0.21.0' = {
params: {
extensionCustomScriptConfig: {
enabled: true
fileData: [
{ uri: 'https://raw.githubusercontent.com/yourrepo/scripts/setup.sh' }
]
settings: {
commandToExecute: 'bash setup.sh --param value'
}
}
}
}1. Squid Proxy
squid-init.yaml (cloud-init)
#cloud-config
# Squid Proxy Server 初期化スクリプト
# 用途: フォワードプロキシサーバー(閉域ネットワークからのインターネットアクセス)
package_update: true
package_upgrade: true
packages:
- squid
- apache2-utils # htpasswd 用
write_files:
# Squid 設定ファイル
- path: /etc/squid/squid.conf
content: |
# === Squid Proxy Configuration ===
# Generated by azure-env-builder
# ポート設定
http_port 3128
# ACL 定義
acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
acl localnet src 192.168.0.0/16
acl SSL_ports port 443
acl Safe_ports port 80 443 8080
acl CONNECT method CONNECT
# Azure サービスエンドポイント許可
acl azure_endpoints dstdomain .azure.com
acl azure_endpoints dstdomain .microsoft.com
acl azure_endpoints dstdomain .windows.net
acl azure_endpoints dstdomain .azure-api.net
# アクセス制御
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localnet
http_access deny all
# キャッシュ設定
cache_mem 256 MB
maximum_object_size 50 MB
cache_dir ufs /var/spool/squid 1000 16 256
# ログ設定
access_log /var/log/squid/access.log squid
cache_log /var/log/squid/cache.log
# プライバシー
forwarded_for off
request_header_access Via deny all
request_header_access X-Forwarded-For deny all
# パフォーマンス
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320
permissions: "0644"
runcmd:
# Squid 初期化
- squid -z
- systemctl enable squid
- systemctl restart squid
# ファイアウォール設定
- ufw allow 3128/tcp
- echo "Squid proxy installed and running on port 3128" > /var/log/cloud-init-complete.logsquid-setup.sh (CustomScriptExtension)
#!/bin/bash
# Squid Proxy Setup Script
# Usage: bash squid-setup.sh --allowed-networks "10.0.0.0/8,172.16.0.0/12" --proxy-port 3128
set -e
# === パラメータ解析 ===
ALLOWED_NETWORKS="10.0.0.0/8"
PROXY_PORT="3128"
while [[ "$#" -gt 0 ]]; do
case $1 in
--allowed-networks) ALLOWED_NETWORKS="$2"; shift ;;
--proxy-port) PROXY_PORT="$2"; shift ;;
*) echo "Unknown parameter: $1"; exit 1 ;;
esac
shift
done
echo "=== Installing Squid Proxy ==="
apt-get update
apt-get install -y squid
# ACL 生成
ACL_LINES=""
IFS=',' read -ra NETWORKS <<< "$ALLOWED_NETWORKS"
for network in "${NETWORKS[@]}"; do
ACL_LINES+="acl allowed_net src $network\n"
done
# 設定ファイル生成
cat > /etc/squid/squid.conf << EOF
http_port ${PROXY_PORT}
# 許可ネットワーク
$(echo -e "$ACL_LINES")
acl SSL_ports port 443
acl Safe_ports port 80 443 8080
acl CONNECT method CONNECT
# Azure サービス
acl azure dstdomain .azure.com .microsoft.com .windows.net
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow allowed_net
http_access deny all
cache_mem 256 MB
forwarded_for off
EOF
# サービス再起動
systemctl enable squid
systemctl restart squid
echo "=== Squid Proxy Ready on port ${PROXY_PORT} ==="2. Nginx リバースプロキシ
nginx-init.yaml (cloud-init)
#cloud-config
# Nginx Reverse Proxy + Let's Encrypt 初期化スクリプト
package_update: true
package_upgrade: true
packages:
- nginx
- certbot
- python3-certbot-nginx
write_files:
# 基本設定
- path: /etc/nginx/sites-available/reverse-proxy
content: |
# === Nginx Reverse Proxy Configuration ===
upstream backend {
# バックエンドサーバー (Bicep から動的に設定)
server 10.0.1.10:8080;
keepalive 32;
}
server {
listen 80;
server_name _;
# Let's Encrypt 認証用
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# HTTPS へリダイレクト
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name _;
# SSL 設定 (Let's Encrypt で後から更新)
ssl_certificate /etc/nginx/ssl/default.crt;
ssl_certificate_key /etc/nginx/ssl/default.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# セキュリティヘッダー
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# プロキシ設定
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
}
# ヘルスチェック
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
permissions: "0644"
runcmd:
# SSL 自己署名証明書 (初期用)
- mkdir -p /etc/nginx/ssl
- openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/default.key -out /etc/nginx/ssl/default.crt -subj "/CN=localhost"
- mkdir -p /var/www/certbot
# サイト有効化
- ln -sf /etc/nginx/sites-available/reverse-proxy /etc/nginx/sites-enabled/
- rm -f /etc/nginx/sites-enabled/default
- nginx -t
- systemctl enable nginx
- systemctl restart nginxnginx-setup.sh (CustomScriptExtension)
#!/bin/bash
# Nginx Reverse Proxy Setup
# Usage: bash nginx-setup.sh --backend "10.0.1.10:8080" --domain "example.com" --email "admin@example.com"
set -e
BACKEND="localhost:8080"
DOMAIN=""
EMAIL=""
while [[ "$#" -gt 0 ]]; do
case $1 in
--backend) BACKEND="$2"; shift ;;
--domain) DOMAIN="$2"; shift ;;
--email) EMAIL="$2"; shift ;;
*) echo "Unknown parameter: $1"; exit 1 ;;
esac
shift
done
echo "=== Installing Nginx ==="
apt-get update
apt-get install -y nginx certbot python3-certbot-nginx
# 設定ファイル生成
cat > /etc/nginx/sites-available/reverse-proxy << EOF
upstream backend {
server ${BACKEND};
keepalive 32;
}
server {
listen 80;
server_name ${DOMAIN:-_};
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
mkdir -p /var/www/certbot
ln -sf /etc/nginx/sites-available/reverse-proxy /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
nginx -t
systemctl enable nginx
systemctl restart nginx
# Let's Encrypt (ドメイン指定時のみ)
if [[ -n "$DOMAIN" && -n "$EMAIL" ]]; then
certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos -m "$EMAIL"
fi
echo "=== Nginx Reverse Proxy Ready ==="3. Docker + Docker Compose
docker-init.yaml (cloud-init)
#cloud-config
# Docker + Docker Compose 初期化スクリプト
package_update: true
package_upgrade: true
packages:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- lsb-release
runcmd:
# Docker リポジトリ追加
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
- apt-get update
- apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# azureuser を docker グループに追加
- usermod -aG docker azureuser
# Docker サービス有効化
- systemctl enable docker
- systemctl start docker
# Azure CLI インストール (ACR 認証用)
- curl -sL https://aka.ms/InstallAzureCLIDeb | bash
# Docker ログイン設定 (Managed Identity)
- az login --identity
- echo "Docker installed and ready" > /var/log/cloud-init-complete.log
write_files:
# Docker daemon 設定
- path: /etc/docker/daemon.json
content: |
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2"
}
permissions: "0644"docker-compose-app.yaml (サンプル)
# サンプル Docker Compose ファイル
# /opt/app/docker-compose.yaml として配置
version: "3.8"
services:
web:
image: ${ACR_NAME}.azurecr.io/${APP_NAME}:${IMAGE_TAG:-latest}
ports:
- "8080:8080"
environment:
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=${REDIS_URL}
- APPINSIGHTS_INSTRUMENTATIONKEY=${APPINSIGHTS_KEY}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
redis:
image: redis:alpine
restart: unless-stopped
volumes:
- redis-data:/data
volumes:
redis-data:4. Windows IIS
iis-setup.ps1 (CustomScriptExtension)
# IIS + ASP.NET Core Hosting Bundle インストール
# Usage: powershell -ExecutionPolicy Unrestricted -File iis-setup.ps1 -DotNetVersion "8.0" -AppPoolName "MyApp"
param(
[string]$DotNetVersion = "8.0",
[string]$AppPoolName = "DefaultAppPool",
[string]$SiteName = "Default Web Site",
[string]$AppPath = "C:\inetpub\wwwroot"
)
Write-Host "=== Installing IIS and ASP.NET Core ===" -ForegroundColor Cyan
# IIS インストール
Install-WindowsFeature -Name Web-Server -IncludeManagementTools
Install-WindowsFeature -Name Web-Asp-Net45
Install-WindowsFeature -Name Web-WebSockets
# ASP.NET Core Hosting Bundle ダウンロード
$hostingBundleUrl = "https://download.visualstudio.microsoft.com/download/pr/hosting-bundle-$DotNetVersion-latest.exe"
$hostingBundlePath = "$env:TEMP\hosting-bundle.exe"
Write-Host "Downloading ASP.NET Core Hosting Bundle..." -ForegroundColor Yellow
Invoke-WebRequest -Uri $hostingBundleUrl -OutFile $hostingBundlePath
# サイレントインストール
Start-Process -FilePath $hostingBundlePath -ArgumentList "/quiet /norestart" -Wait -NoNewWindow
# IIS 再起動
net stop was /y
net start w3svc
# アプリケーションプール設定
Import-Module WebAdministration
if (-not (Test-Path "IIS:\AppPools\$AppPoolName")) {
New-WebAppPool -Name $AppPoolName
}
Set-ItemProperty "IIS:\AppPools\$AppPoolName" -Name managedRuntimeVersion -Value ""
Set-ItemProperty "IIS:\AppPools\$AppPoolName" -Name startMode -Value "AlwaysRunning"
# ファイアウォール設定
New-NetFirewallRule -DisplayName "HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
New-NetFirewallRule -DisplayName "HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
Write-Host "=== IIS Ready ===" -ForegroundColor Green5. 共通ユーティリティ
common-init.yaml (cloud-init ベース)
#cloud-config
# 共通初期化スクリプト (Linux)
# すべての VM に適用する基本設定
package_update: true
package_upgrade: true
packages:
- curl
- wget
- jq
- unzip
- htop
- vim
- git
# Azure CLI インストール
runcmd:
- curl -sL https://aka.ms/InstallAzureCLIDeb | bash
# Azure Monitor Agent 用の準備
- mkdir -p /var/log/azure
# タイムゾーン設定
- timedatectl set-timezone Asia/Tokyo
# スワップ設定
- fallocate -l 2G /swapfile
- chmod 600 /swapfile
- mkswap /swapfile
- swapon /swapfile
- echo '/swapfile none swap sw 0 0' >> /etc/fstab
write_files:
# 便利なエイリアス
- path: /etc/profile.d/custom-aliases.sh
content: |
alias ll='ls -la'
alias az-login='az login --identity'
alias k='kubectl'
permissions: "0644"Bicep での使用例
// Squid Proxy VM デプロイ
module squidVm 'br/public:avm/res/compute/virtual-machine:0.21.0' = {
name: 'squidVmDeployment'
params: {
name: 'vm-squid-${environment}'
vmSize: 'Standard_B2ms'
imageReference: {
publisher: 'Canonical'
offer: '0001-com-ubuntu-server-jammy'
sku: '22_04-lts-gen2'
version: 'latest'
}
osType: 'Linux'
nicConfigurations: [
{
ipConfigurations: [
{ subnetResourceId: proxySubnetId }
]
enableIPForwarding: true
}
]
adminUsername: 'azureuser'
disablePasswordAuthentication: true
publicKeys: [
{ path: '/home/azureuser/.ssh/authorized_keys', keyData: sshPublicKey }
]
// cloud-init で Squid 自動インストール
customData: loadFileAsBase64('../../scripts/vm-init/squid-init.yaml')
}
}
// UDR で Squid 経由にルーティング
module routeTable 'br/public:avm/res/network/route-table:0.5.0' = {
name: 'routeTableDeployment'
params: {
name: 'rt-via-squid-${environment}'
routes: [
{
name: 'to-internet-via-squid'
addressPrefix: '0.0.0.0/0'
nextHopType: 'VirtualAppliance'
nextHopIpAddress: squidVm.outputs.privateIPAddress
}
]
}
}