Accept cookies for analytics, social media, and advertising, or learn more and adjust your preferences. These cookies are on by default for visitors outside the UK and EEA. Privacy Notice.
この良い小さなソフトウェアについて Igor Sysoev に感謝します。これは、私にとってこの偉大なプロジェクトに何か貢献できる唯一の方法です。私達が単純に"SSL-Proxy"と呼ぶものを確立する全体像を説明しようとしました(別名、SSL/TLS/HTTPS-Offloader/-Accelerator/-Terminator/-Dispatcher/Reverse-Proxy/Loadbalancer など)。
私達の会社では、NGINXをリバースプロキシとして使い、複数のバックエンドからHTTPを使ってコンテントを受け取る時にクライアントにHTTPSを提供しています。VRRPを使って1つのクラスタに"接続"している2つのバーチャルマシーンがあり、それぞれが1つ以上のアプリケーションを持つ約80のTomcatサーバ(およびいくつかのIIS, Apache/PHP...)のためのフロントエンドとして振舞います。この構造には多くの理由がありました: SSL証明書用の1つのCI (ITIL: アイテムの変更)、顧客の要求 (複数のサービスを持つ1つのURL)、変更に対する単純だが効果的なフェイルオーバー機構など。
始めに、ちょっとした警告です。
サーバはとても効率的に動作します:
ポリシーのようなもの...
include
ファイルの幾つかの追加の参照と複雑な配置につながります。if
-ステートメントは入れ子にすべきではありません。したがってincludeの中にinclude
-ステートメントを使うことは避けます。/etc/nginx
の中に新しく生成されたファイル:
1つの内部(ADS)ドメイン、幾つかの公のそれ、そして複雑な状況がありました:
私達の解決方法は、2つの大きなDNSの木から始め、アプリケーション名をDNSからパスへ移動するものでした:
http(s)://<app-group>.<customer>.<channel>.<segment>.[local|labor]/<application>/
製品システムの場合、公的なドメインにマップされていました。
Tip
pdnsd
を使います。*.local
ドメインを使う必要がないかも知れません。最も重要なこと...
Remote IP Valve
を使います。ネットワーク設定を/etc/sysctl.d/10-network-security.conf
ファイルに置きました。設定の幾つかは既に下の設定の中にありました。
### http://www.cyberciti.biz/tips/linux-unix-bsd-nginx-webserver-security.html
# Avoid a smurf attack
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Turn on protection for bad icmp error messages
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Turn on syncookies for SYN flood attack protection
net.ipv4.tcp_syncookies = 1
# Turn on and log spoofed, source routed, and redirect packets
#net.ipv4.conf.all.log_martians = 1
#net.ipv4.conf.default.log_martians = 1
# No source routed packets here
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Turn on reverse path filtering
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Make sure no one can alter the routing tables
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
# Don't act as a router
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
# Turn on execshild
kernel.exec-shield = 1
kernel.randomize_va_space = 1
# Tuen IPv6
net.ipv6.conf.default.router_solicitations = 0
net.ipv6.conf.default.accept_ra_rtr_pref = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.default.dad_transmits = 0
net.ipv6.conf.default.max_addresses = 1
# Optimization for port usefor LBs
# Increase system file descriptor limit
fs.file-max = 65535
# Allow for more PIDs (to reduce rollover problems)
# !!! may break some programs 32768
#kernel.pid_max = 65536
# Increase system IP port limits
net.ipv4.ip_local_port_range = 2000 65000
# Increase TCP max buffer size setable using setsockopt()
net.ipv4.tcp_rmem = 4096 87380 8388608
net.ipv4.tcp_wmem = 4096 87380 8388608
# Increase Linux auto tuning TCP buffer limits
# min, default, and max number of bytes to use
# set max to at least 4MB, or higher if you use very high BDP paths
# Tcp Windows etc
net.core.rmem_max = 8388608
net.core.wmem_max = 8388608
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_window_scaling = 1
これは1つのシステムのVRRP設定 /etc/keepalived/keepalived.conf
です。2つのインスタンスの設定があります。障害時には、両方のVRRPのアドレスが、残っているシステムに所属します。2つ目のシステムのために、"state"と"priority"の値を変更します。
注意
インタフェースをプロミスカスモードに設定した後で、keepalived
を再起動する必要があります例えば、デバッグのためにtcpdumpを使う場合)。
vrrp_instance ONE {
state MASTER
priority 120
interface eth0
virtual_router_id <id-1>
advert_int 1
authentication {
auth_type pass
auth_pass <pass-1>
}
virtual_ipaddress_excluded {
<vrrp-ipv4-1>
<vrrp-ipv6-1>
}
}
vrrp_instance TWO {
state BACKUP
priority 80
interface eth0
virtual_router_id <id-2>
advert_int 1
authentication {
auth_type pass
auth_pass <pass-2>
}
virtual_ipaddress_excluded {
<vrrp-ipv4-2>
<vrrp-ipv6-2>
}
}
1つのありえる解決方法は、NAT(network address translation)ではなく、直接ルーティングを使うことです。この場合は、NGINX設定のサーバに一致するローカルIPアドレスが必要です。/etc/network/interfaces
ファイルの中に、このようにダミー(あるいはループバック)のための post-up
コマンドを追加することができます。モジュールdummy
を /etc/modules
に追加するのを忘れないでください。
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
...
post-up /etc/nginx/conf.d/ip-mtu.sh
iface eth0 inet6 static
...
auto dummy0
iface dummy0 inet manual
up /sbin/ip link set dummy0 up
post-up /etc/nginx/conf.d/ip-addr.sh
down /sbin/ip link set dummy0 down
参照したスクリプトは幾つかのarp発行を訂正し、ルートされたネットワークのping-pongパケットを避けるためにブラックホールルーティングを行い、もちろんネットワークアドレスを追加します。
#!/bin/bash
echo 0 > /proc/sys/net/ipv4/ip_no_pmtu_disc
echo 1 > /proc/sys/net/ipv4/tcp_mtu_probing
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/dummy0/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/dummy0/arp_ignore
ip route add blackhole <network-1>
ip route add blackhole <network-2>
...
ip route add blackhole <network-n>
ip addr add <address-1>/32 dev dummy0 label <label-1>
ip addr add <address-2>/32 dev dummy0 label <label-2>
...
ip addr add <address-x>/32 dev dummy0 label <label-x>
おそらく、全ての設定に2番目のフィルタが必要であり、ネットワークインタフェースが機能している必要があります (例えば、一部の MTU/MSS 値を修正する必要がある場合は、実際のインタフェースで実際の IP にルーティングする必要があります)。
#!/bin/bash
# VPN Networks with broken PMTU
# (ADVMSS = MTU - 40)
ip route add <host-/network-1> via <default gateway> mtu <mtu> advmss <mtu-40>
ip route add <host-/network-2> via <default gateway> mtu <mtu> advmss <mtu-40>
...
ip route add <host-/network-m> via <default gateway> mtu <mtu> advmss <mtu-40>
デフォルトの設定ファイル /etc/nginx/nginx.conf
にあまり変更をしないことに決めました。VMは4つのコアを持ち、各コアは1つの固定のworkerを取り、NGINXは他のプロセスよりも優先度を高くしたいです。他の全ての設定はincludeされていました(includeされるファイルmime.types
はプロジェクトHTML5-Boilerplateから選ばれています)。
worker_processes 4;
worker_priority -1;
worker_rlimit_nofile 8192;
worker_cpu_affinity 0001 0010 0100 1000;
user www-data;
pid /var/run/nginx.pid;
error_log /var/log/nginx/error.log;
events {
multi_accept on;
worker_connections 4096;
}
http {
map_hash_bucket_size 128;
include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
ファイル/etc/nginx/conf.d/sslproxy.conf
は全ての重要なグローバル設定を持ちます。特に:
### global ###
server_tokens off;
server_name_in_redirect off;
ignore_invalid_headers on;
if_modified_since before;
root /etc/nginx/content/;
ssi on;
ssi_silent_errors on; # testing=off
add_header X-Frame-Options SAMEORIGIN;
add_header Strict-Transport-Security max-age=16000000;
### tcp ###
tcp_nodelay off;
tcp_nopush on;
sendfile on;
keepalive_requests 100;
### timeouts ###
resolver_timeout 6;
client_header_timeout 30;
client_body_timeout 60;
send_timeout 60;
keepalive_timeout 65 20;
### buffers ###
client_header_buffer_size 1k;
client_body_buffer_size 128k;
large_client_header_buffers 4 4k;
client_max_body_size 10m;
client_body_temp_path /var/spool/nginx/client/;
output_buffers 1 32k;
postpone_output 1460;
### errors ###
recursive_error_pages off;
error_page 400 402 403 405 406 410 411 413 416 /40x.html;
error_page 500 501 502 503 504 /50x.html;
error_page 404 =410 /40x.html;
error_page 443 =200 /test.png;
open_log_file_cache max=1024 inactive=30s min_uses=3 valid=5m;
### acl ###
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
deny all;
### ssl ###
ssl on;
#ssl_stapling on; # selfsigned=off
#ssl_stapling_verify on; # selfsigned=off
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!RC4:!3DES:!aDSS:!aNULL:!kPSK:!kSRP:!MD5:@STRENGTH:+SHA1:+kRSA;
ssl_session_cache shared:TLSSL:16m;
ssl_session_timeout 10m;
ssl_certificate sslcert/de/<company>/wildcard.crt;
ssl_certificate_key sslcert/de/<company>/wildcard.key;
### compression ###
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_min_length 128;
gzip_buffers 128 32k;
gzip_comp_level 6;
gzip_proxied any;
gzip_types text/plain text/css text/x-component
text/xml application/xml application/xhtml+xml application/json
image/x-icon image/bmp image/svg+xml application/atom+xml
text/javascript application/javascript application/x-javascript
application/pdf application/postscript
application/rtf application/msword
application/vnd.ms-powerpoint application/vnd.ms-excel
application/vnd.ms-fontobject application/vnd.wap.wml
application/x-font-ttf application/x-font-opentype;
### proxy-global ###
#resolver <dns-proxy>; # we use "pdnsd" here
proxy_intercept_errors on; # testing=off
proxy_ignore_client_abort off;
proxy_redirect http:// $scheme://;
### proxy-header ###
proxy_hide_header Server;
proxy_hide_header X-Powered-By;
proxy_hide_header X-AspNet-Version;
proxy_set_header Accept-Encoding ""; # no backend compression
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Class $classification; # our internal custom header
proxy_set_header X-Forwarded-Proto $scheme;
map $scheme $msiis { http off; https on; } # compatibility
proxy_set_header Front-End-Https $msiis;
### proxy-timeouts ###
proxy_connect_timeout 6;
proxy_send_timeout 60;
proxy_read_timeout 60;
### proxy-buffers ###
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 256 8k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_temp_path /var/spool/nginx/temp/;
幾つかの追加の情報が必要な場合、この設定ファイル/etc/nginx/conf.d/logging.conf
は記録を引き起こさなければなりません。SSLプロキシをネットワークデバイスとして定義したため、したがってアプリケーションはユーザアクセスを記録する責任があります。
log_format apache
'$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_cookie"';
log_format full
'$remote_addr $remote_user [$time_local] '
'"$host"->$proxy_host->$upstream_addr '
'"$request" $status($upstream_status) '
'$bytes_sent/$gzip_ratio($sent_http_content_type) '
'$request_time($upstream_response_time)';
log_format perf
'$request_time($upstream_response_time) '
'$bytes_sent/$gzip_ratio($sent_http_content_type) '
'$status "$upstream_addr$uri"';
log_format gzip
'$bytes_sent/$gzip_ratio($sent_http_content_type) '
'[$http_accept_encoding]"$http_user_agent"';
log_format redirect
'$time_local $redir_match $redir_action $redir_url';
#access_log off;
access_log /var/log/nginx/access.log apache;
#access_log /var/log/nginx/access-full.log full;
#access_log /var/log/nginx/access-perf.log perf;
#access_log /var/log/nginx/access-gzip.log gzip;
このファイルをIDを持つ2つのバックエンドサーバの関係を定義するために使います。NGINXの構文はこれらの定義をグローバルにするだけです。このことは、新しい1つのバックエンド/アップストリームを定義した場合に2つのファイルをtouchする必要があることを意味します。
upstream <backend-id-1> {
server <server-ip-1.1>:<internal-port>;
server <server-ip-1.2>:<internal-port> backup;
}
upstream <backend-id-2> {
server <server-ip-2.1>:<internal-port>;
server <server-ip-2.2>:<internal-port> backup;
}
...
upstream <backend-id-n> {
server <server-ip-n.1>:<internal-port>;
server <server-ip-n.2>:<internal-port> backup;
}
ssl-proxyの最近のバージョンでは、亜フィルは/etc/nginx/scripts/gen-upstream.conf
を使ってアプリケーション定義から自動的に生成されます。つまり、これで1つのpath_<context>
ファイルによって新しいサービスを追加することができます。
#!/bin/sh
START=`pwd`
cd /etc/nginx
cat mapping/dem/path_* | grep "#UP#" | cut -c "6-" > conf.d/upstream.dem-auto.conf
cat mapping/prd/path_* | grep "#UP#" | cut -c "6-" > conf.d/upstream.prd-auto.conf
nginx -t
cd $START
これは/etc/nginx/mapping/<segment>/<application>
にあるデフォルトのアプリケーションの例で、これはほとんどの場合に当てはまるはずです。最初の部分はバックエンド設定の自動生成のために使われるコメントです。
#UP# upstream <backend-id-n> {
#UP# server <server-ip-n.1>:<internal-port>;
#UP# server <server-ip-n.2>:<internal-port> backup;
#UP# }
location /<app-path>/ { proxy_pass http://<backend-id>; }
幾つかのwebアプリケーションはrootパスをサブディレクトリに変更することを許可しません。それらのうちの一つをサーバ設定の中のサブディレクトリを使ってアプリケーションと組み合わせて使うことができます。proxy_intercept_errors
機能を使いたい場合は、if
-ステートメントを追加する必要があります。
location / {
if (-f $request_filename) { break; }
proxy_pass http://<backend-id>;
}
CMSシステムの編集ページのような幾つかのアプリケーションはしばしば追加の必要があります。例えば映画あるいは大きなPDFをアップロードしたいとします。その場合アップロードの最大サイズを調整する必要があります。
location /<app-path>/ {
client_max_body_size 100m;
proxy_pass http://<backend-id>; }
アプリケーションの応答が長く掛かり(例えば、レポートの生成)、keepaliveの仕組みが利用できない(私達の場合は"BIRT"フレームワークでした)場合、タイムアウトのデフォルトの設定を、クライアントおよびサーバ側で、予定以上に使いました。
location /<app-path>/ {
send_timeout 3600;
proxy_read_timeout 3600;
proxy_pass http://<backend-id>;
}
クライアントと情報を交換するデフォルトの方法のため、SOAPは タイプ500のエラーを変更しないことを必要とします。
location /<app-path>/ {
proxy_intercept_errors off;
proxy_pass http://<backend-id>;
}
この例は、1つの簡単なアプリケーションを使ってインターネット(全てを許可)サーバを説明します。rewriteルールはアプリケーションディレクトリに初期リダイレクトを行います。以下のindexページはアプリケーションの責任下にあります。
server {
ssl_certificate sslcert/<dns-domain>/<subdomain>.crt;
ssl_certificate_key sslcert/<dns-dmoain>/<subdomain>.key;
listen <ip>:443; allow all;
server_name <ip> <dns>;
set $classification "<customer>.<channel>.<segment>";
rewrite ^/+$ /<app-path>/ redirect;
include mapping/<segment>/<app-path>
}
これは私達のセットアップの中でより複雑なうちの一つです。古い/レガシー URLをスムーズに変更する必要がある場合にのみ、これを実装してください。
Motivation / Goal:
www.
プリフィックスの暗黙的な一致map $redir_match $redir_target { hostnames;
#[<context>.]<hostname> #(static|refresh|redirect)@<scheme>://<target>/<context>/;
my-app-1.old-url.com redirect@https://new-url.com/my-app-1/;
.old-url.com redirect@https://new-url.com/default-app/;
if ($redir_target ~* ^(.*)@(.*)) { set $redir_action $1; set $redir_url $2; }
if ($redir_action = "static") { rewrite ^ /301-static.html last; }
if ($redir_action = "refresh") { rewrite ^ /301-refresh.html last; }
if ($redir_action = "redirect") { rewrite ^ $redir_url permanent; break;
access_log /var/log/nginx/redirector.log redirect;}
server {
allow all;
listen 80 default; ssl off;
listen 443 default ssl;
server_name <dns-name>;
include mapping/security.ext;
location / {
# deliver local files
if (-f $request_filename) { break; }
# redirector
set $redir_host $http_host;
if ($http_host ~* ^www\.(.*)) { set $redir_host $1; }
if ($uri ~* ^/([^/]+)) { set $redir_context $1.; }
set $redir_match $redir_context$redir_host;
include mapping/redir.action;
# global https enforcement
if ($scheme = "http") {
rewrite ^ https://$http_host$request_uri permanent; }
}
location /status {
stub_status on;
allow <monitoring system>;
deny all;
}
}
この部分はとても特別です: カスタマーのほとんどがsignonページ(SSOシステム)をブックマックしているため、これをrewriteすることも注意しなければなりません。
location /<login-app>/ {
if ( $arg_<return-url> ~* ^https?(://|%3A%2F%2F)([^/%]+)(/|%2F)([^/%]*) ) {
set $redir_match $4.$2; }
include mapping/redirector.action;
proxy_pass http://<backend-id>;
}
これは幾つかの異なるExchangeサーバのための単なるゲートウェイ (証明書無し!)です。dnsエントリに対して、デバイスの幾つかの"fingerprint"を検証します。コードはサービスとして上記のコンテキストファイルに “plugged” することができます。
location /Microsoft-Server-ActiveSync {
access_log /var/log/nginx/activesync.log;
resolver your.dns.server.ip;
# deny anonymous; deny other http methods
if ( $remote_user = "" ) { return 444; break; }
if ( $request_method !~* ^(POST|OPTIONS)$ ) { return 444; break; }
# extract domain and user-id
if ( $remote_user ~* ^(.+)\x5C(.+)$ ) { set $domain $1; set $userid $2; }
if ( $remote_user !~* ^(.+)\x5C(.+)$ ) { return 444; break; }
# replace underscores in username
if ( $userid ~* ^(.+)_(.+)$ ) { set $userdn $1x$2; }
if ( $userid !~* ^(.+)_(.+)$ ) { set $userdn $userid; }
# extract device-type and version
if ( $http_user_agent ~* ^MSFT-(.+)/(.+)\.(.+)\.(.+)$ ) { set $device MSFT$1; set $versio $2x$3x$4; }
if ( $http_user_agent ~* ^Apple-iPhone(.*)/(.+)\.(.+)$ ) { set $device iPhone; set $versio $1x$2x$3; }
if ( $http_user_agent ~* ^Apple-iPad(.+)/(.+)\.(.+)$ ) { set $device iPad; set $versio $1x$2x$3; }
if ( $http_user_agent ~* ^Apple-iPod(.+)/(.+)\.(.+)$ ) { set $device iPod; set $versio $1x$2x$3; }
if ( $http_user_agent ~* ^Android-(.+)/(.+)\.(.+)$ ) { set $device Android; set $versio $1x$2x$3; }
# always allow initial requests without arguments
set $initia $request_method:$args;
if ( $initia ~* ^OPTIONS:$ ) { set $target $domain-exchange; set $versio ok; }
if ( $versio = "" ) { return 444; break; }
# set target, if usernames match
if ( $userid = $arg_User ) { set $target $domain-$userdn-$arg_DeviceId-$device-$versio; }
# forward request
proxy_pass http://$target.your.internal.sync.domain;
}
失敗したリクエストはリゾルバ エラーとしてerror.log
の中に現れます。error.log
はrsyslogによって監視され、syslogサーバに転送されました。syslogサーバは内部ドメインをチェックし、サポートにメールを送信します。
...
# Mail-Trap: ActiveSync
$ActionExecOnlyOnceEveryInterval 300
$ActionMailTo recicpient-1@your.company
$ActionMailTo recicpient-2@your.company
:msg,contains,"your.internal.sync.domain" :ommail:;mailBody
...
手短に: NGINXはSyslogをサポートしません。 したがって、Syslogサポートを必要とする場合は幾つかの取りうる方法があります。
error.log
については良いです。access.logをローカルに2回保存したくはないので、access.log
が消費する領域については良い考えではありません。# export via udp *.notice;local0,local1,local2,local3,local4,local5,local6,local7.*;mark,cron.none @<syslog-server>
# import-module: file $ModLoad imfile # nginx/error.log $InputFileName /var/log/nginx/error.log $InputFileTag nginx: $InputFileStateFile nginx_error.log $InputFileSeverity warning $InputFileFacility local7 $InputRunFileMonitor # send and drop :syslogtag,isequal,"nginx:" @<syslog-server> & ~
/etc/cron.daily/logfile-actionsを作成します。これは毎日実行され、そこにクリーンアップコマンドを配置します (例えば、アクセスログについては1日、その他全てについては6ヶ月)。chmod +x
するのを忘れないでください。これにより、少なくともローカルに彩度保存したくない全てのファイルが処理されます。しかし、以前言ったように、1日のアクセスログの量があまり大きく無い場合にのみ動作します... そしてそれはあまりスマートではありません。
#!/bin/sh
find /var/log/ -name *.gz -mtime +180 -delete
find /var/log/nginx/ -name access*.gz -mtime +2 -delete
毎日の使用のための最も重要なスクリプトです。しかし、年を重ねるに連れて、とても醜いものになっています。
#!/bin/bash
case `hostname` in
"sslproxy-01" )
PEER="sslproxy-02";;
"sslproxy-02" )
PEER="sslproxy-01";;
esac
START=`pwd`
/etc/init.d/nginx reload
sleep 2
chown www-data:adm /var/log/nginx/*
/etc/init.d/keepalived reload
cd /etc/nginx/sslcert/
tar -cvjpf /etc/nginx/sslcert.tbz2 ./*
cd $START
echo "
put -P /etc/cron.daily/logfile-actions /etc/cron.daily/
put -P /etc/sysctl.d/10-network-security.conf /etc/sysctl.d/
put -P /etc/monit/monitrc /etc/monit/
put -P /etc/monit/conf.d/* /etc/monit/conf.d/
put -P /etc/keepalived/keepalived.conf /etc/keepalived/remote.conf
put -P /etc/keepalived/remote.conf /etc/keepalived/keepalived.conf
put -P /etc/nginx/sslcert.tbz2 /etc/nginx/
put -P /etc/nginx/nginx.conf /etc/nginx/
rm /etc/nginx/conf.d/*
put -P /etc/nginx/conf.d/* /etc/nginx/conf.d/
rm /etc/nginx/content/*
put -P /etc/nginx/content/* /etc/nginx/content/
rm /etc/nginx/scripts/*
put -P /etc/nginx/scripts/* /etc/nginx/scripts/
rm /etc/nginx/sites-enabled/*
put -P /etc/nginx/sites-enabled/* /etc/nginx/sites-enabled/
rm /etc/nginx/mapping/*
rm /etc/nginx/mapping/dem/*
rm /etc/nginx/mapping/prd/*
put -P /etc/nginx/mapping/* /etc/nginx/mapping/
put -P /etc/nginx/mapping/dem/* /etc/nginx/mapping/dem/
put -P /etc/nginx/mapping/prd/* /etc/nginx/mapping/prd/
rm /etc/nginx/access/*
rm /etc/nginx/access/lan/*
rm /etc/nginx/access/ext/*
rm /etc/nginx/access/vn1/*
rm /etc/nginx/access/vn2/*
put -P /etc/nginx/access/* /etc/nginx/access/
put -P /etc/nginx/access/lan/* /etc/nginx/access/lan/
put -P /etc/nginx/access/ext/* /etc/nginx/access/ext/
put -P /etc/nginx/access/vn1/* /etc/nginx/access/vn1/
put -P /etc/nginx/access/vn2/* /etc/nginx/access/vn2/
bye
" | sftp -C root@$PEER
rm /etc/nginx/sslcert.tbz2
ssh $PEER '
cd /etc/nginx/sslcert/
rm -rf ./*
tar -xvjpf /etc/nginx/sslcert.tbz2
rm /etc/nginx/sslcert.tbz2
/etc/init.d/nginx reload
chown www-data:adm /var/log/nginx/*
/etc/init.d/keepalived reload
'
exit 0
"正規化"設定ファイルを生成します。基本的に、include-ステートメントを評価し、空白とコメントを削除する再帰的なスクリプトです。これは、バックアップ/リストア、ssl検証などを行う私のほとんどのスクリプトの基本です。おそらく綺麗でも無く、完全でもありませんが、動作します。
#!/bin/sh
START=`pwd`
cd /etc/nginx
if [ -x $0 ]
then CMD=$0
else CMD=$START/$0
fi
if [ "$1" ]
then FILE=$1
else FILE="nginx.conf"
fi
echo "# start: $FILE"
cat $FILE | awk '{
gsub("#.*","",$0);
gsub(";",";\n",$0);
gsub("{","\n{\n",$0);
gsub("}","\n}\n",$0);
print;
}' | awk -v HK="'" -v CMD=$CMD '{
gsub("[ \t]+"," ",$0);
gsub("^[ \t]","",$0);
gsub("[ \t]$","",$0);
gsub(HK,"%%",$0);
if ($1=="include") {
sub(";$","",$2);
print CMD" "HK$2HK; }
else {
print "echo "HK$0HK; }
}' | sh | awk -v HK="'" '{
gsub("%%",HK,$0);
if ($0=="") {
pass; }
else {
print; }
}' | cat
echo "# stop: $FILE"
cd $START
#exit 0
このスクリプトは幾つかのサービスを再起動し、ログファイルを削除し、大きな変更の場合にループバックアドレスを再活性化します。開発システムで特に使います。製品マシーン上では、意図しないリブート時に正しく全てのことが開始されるように、そうしないで変更を行ってから再起動します。
#!/bin/bash
/etc/init.d/monit stop
/etc/init.d/keepalived stop
/etc/init.d/nginx stop
ifconfig -a | grep "lo:" | awk '{print "ifconfig "$1" down"}' | sh
chmod +x /etc/nginx/conf.d/ip-addr.sh
chmod -R +x /etc/nginx/scripts/*
chmod -R 600 /etc/nginx/sslcert/*
rm /var/log/monit
rm /var/log/nginx/*
# other commands, like "apt-get -y upgrade"
/etc/nginx/conf.d/ip-addr.sh
/etc/init.d/nginx start
/etc/init.d/keepalived start
/etc/init.d/monit start
exit 0
include @<identifier>
のようなステートメントと、include { include_name <identifier>; ... }
のようなブロックを使って、全ての include の個々のファイルを含むことを回避できます。