2018年のサーバー構築

2018-01-16 20:50:07 +09:00 Post Comments

本サイトは2018年1月12日〜14日ごろに、3代目の機体(5代目くらいの構築)で公開を再開しました。 本記事はその記録です。

基本方針

今回の再構築では次の基本方針を掲げました。

  • 壊れにくい
    • ソフトウェアの更新などによるサービスの停止を起こしにくい
    • 攻撃を食らっても被害をサービス停止までに止める
  • 再構築しやすい
    • 機体の更新などで再構築する場合にも,できる限り短い時間で作業ができる

このサイトはアップデート失敗などで停止し、 再構築に手間取ることによって長期間に渡って公開停止になることを、 繰り返してきました。 再発を防ぐために、壊れにくく直しやすい作りが必要でした。

これらを実現するための方法として、VMを利用して軽量OSを動作させ、 その上でそのOSのやり方に沿ってサイトを構築することとしました。 (いまどき自宅サーバでやっています。 あんまりネットワークに負荷をかけると、 私とはなんの関係もない近隣住民に被害が発生します。 私が気に入らない場合はコメントでお願いします。)

使用ソフトウェア

OS周り

ウェブサーバ

  • HTTP サーバ: nginx
  • コンテンツ管理(VMホスト側で実行): Hugo
  • コメントサーバ: Isso
  • コメントサーバ実行環境: uWSGI

メールサーバ

DNSサーバ(サーバ間連携用)

設定内容

OS周り

各サーバ共通で以下の様な設定をしました。

  • VM作成時のオプションとしては
    • OS: 「Linux 2.6以降」
    • 適当なサイズのストレージを設定
    • ネットワークは「ブリッジアダプター」
  • インストーラを普通に使う
    Login: root
    # インストールCDはrootにパスワードなしで入れる様になっている
    setup-alpine
    
  • communityリポジトリを有効化
    vi /etc/apk/repositories
    
    • 次の通り編集
      http://.../alpine/v3.7/main
      http://.../alpine/v3.7/community ←コメントアウトを解除
      
  • sshでのログインのため、証明書を配置
    • まずホスト側で鍵を作る
      	ssh-keygen -t ed25519 -f .ssh/id_local_(名前)
      
    • SSHクライアント用の設定ファイルを作成しサーバへの接続を容易にする設定
      Host (名前)
      	Hostname (IPアドレス)
      	IdentityFile ~/.ssh/id_local_(名前)
      	User root
      
    • 公開鍵をサーバに配置
      vi ~/.ssh/authorized_keys
      
      • 内容
        ssh-ed25519 ..... ***@****.**
        
  • 以降「apkでインストール」は次のコマンドを表す
    apk add (パッケージ)
    
  • 「自動起動の設定」は次のコマンドを表す
    rc-update add (サービス名) default
    

DNSサーバ

  • apkでdnsmasq-dnssecをインストール
  • 設定は決まった場所にファイルを置いて上書き
    • 内容については dnsmasqで始めるプライベートDNSサーバ - GeekFactory を参考にしております。
      # Never forward plain names (without a dot or domain part)
      domain-needed
      # Never forward addresses in the non-routed address spaces.
      bogus-priv
      
      # Set this (and domain: see below) if you want to have a domain
      # automatically added to simple names in a hosts-file.
      expand-hosts
      
  • /etc/hostsに必要なホストを記載
    127.0.0.1	localhost.localdomain localhost
    192.168.0.3	intdns.airport intdns
    192.168.0.4	mail mail.airport
    192.168.0.5	exserv	exserv.airport xxxx.xx
    

メールサーバ

  • apkで以下をインストール
    • postfix dovecot dovecot-pigeonhole-plugin rspamd rspamd-controller rspamd-proxy redis clamav-daemon
  • 設定していく

メール以外

  • DHCPでは配信してもらえないDNSサーバを見に行かせる
    • /etc/udhcpc/udhcpc.conf に以下を追記

      RESOLV_CONF=no
      
    • /etc/resolv.confを以下の様に変更

      search airport
      nameserver 192.168.0.3
      
  • 証明書を作る
    cd /etc/ssl
    vi local.cf
    
    • local.cfの内容:
      [ req ]
      default_bits = 4096
      encrypt_key = yes
      x509_extensions = extensions
      distinguished_name = req_distinguished_name
      
      [ req_distinguished_name ]
      countryName			= Country Name (2 letter code)
      countryName_min			= 2
      countryName_max			= 2
      stateOrProvinceName		= State or Province Name (full name)
      localityName			= Locality Name (eg, city)
      0.organizationName		= Organization Name (eg, company)
      organizationalUnitName		= Organizational Unit Name (eg, section)
      commonName			= Common Name (eg, fully qualified host name)
      commonName_max			= 64
      emailAddress			= Email Address
      emailAddress_max		= 64
      
      [ extensions ]
      nsCertType = server
      subjectAltName = @alt_names
      
      [alt_names]
      DNS.1 = xxxx.xx
      DNS.2 = mail
      
      • 本当はDNS.3 = mail.airportも書いておかないといけないらしい(手遅れ)
    • 準備ができたので作る
      mkdir dovecot
      cd dovecot
      openssl req -new -x509 -config ../local.cf -newkey rsa:4096 -nodes -keyout server.key -days 3652 -subj /C=JP/ST=Osaka/CN=mail.airport/emailAddress=xxx@xxxx.xx/ -out server.cer
      cd ../postfix/
      openssl req -new -x509 -config ../local.cf -newkey rsa:4096 -nodes -keyout server.key -days 3652 -subj /C=JP/ST=Osaka/CN=mail.airport/emailAddress=xxx@xxxx.xx/ -out server.cer
      

Postfix

  • 次のサイトを参考としております。
  • 設定ファイルに追記
    vi /etc/postfix/main.cf
    
    • 末尾に次の内容を追加する:
      ### ### Local Configurations ### ###
      myhostname = mail.airport
      virtual_mailbox_domains = xxxx.xx
      virtual_mailbox_base = /var/vmail
      virtual_minimum_uid = 100
      virtual_uid_maps = static:5000
      virtual_gid_maps = static:5000
      virtual_alias_maps = hash:/etc/postfix/virtual
      virtual_transport = lmtp:unix:private/dovecot-lmtp
      
      strict_rfc821_envelopes = yes
      smtpd_helo_required = yes
      smtpd_helo_restrictions = reject_non_fqdn_helo_hostname
      smtpd_sender_restrictions = reject_unknown_sender_domain
      smtpd_recipient_restrictions =
       reject_unknown_recipient_domain,
       reject_non_fqdn_recipient,
       reject_unverified_recipient,
       reject_unauth_destination
      unknown_address_reject_code  = 554
      unknown_hostname_reject_code = 554
      unknown_client_reject_code   = 554
      unknown_local_recipient_reject_code = 550
      
      smtpd_tls_cert_file=/etc/ssl/postfix/server.cer
      smtpd_tls_key_file=/etc/ssl/postfix/server.key
      smtpd_tls_security_level = may
      smtp_tls_security_level = may
      
      alias_maps = hash:/etc/postfix/aliases
      mailbox_size_limit = 0
      message_size_limit = 20480000
      queue_run_delay = 300s
      minimal_backoff_time = 300s
      master_service_disable =
      
      smtpd_milters = unix:/var/run/rspamd.sock
      milter_protocol = 6
      milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}
      milter_default_action = accept
      
    • master.cfも編集する
      vi /etc/postfix/master.cf
      
    • 次の通り追記する
      submission inet n       -       n       -       -       smtpd
      	-o syslog_name=postfix/submission
      	-o smtpd_tls_security_level=encrypt
      	-o smtpd_sasl_auth_enable=yes
      	-o smtpd_sasl_type=dovecot
      	-o smtpd_sasl_path=private/auth
      	-o smtpd_sasl_security_options=noanonymous
      	-o smtpd_sasl_local_domain=$myhostname
      	-o smtpd_tls_auth_only=yes
      	-o smtpd_reject_unlisted_recipient=no
      	-o smtpd_client_restrictions=$mua_client_restrictions
      	-o smtpd_helo_restrictions=$mua_helo_restrictions
      	-o smtpd_sender_restrictions=$mua_sender_restrictions
      	-o smtpd_recipient_restrictions=reject_unknown_recipient_domain,reject_non_fqdn_recipient,permit_sasl_authenticated,reject
      	-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
      	-o smtpd_sender_login_maps=hash:/etc/postfix/virtual
      	-o milter_macro_daemon_name=ORIGINATING
      
  • エイリアスを更新
    newaliases
    

Dovecot

  • 次のサイトを参考としております。
  • 全ての設定を追加のファイルで行う
    vi /etc/dovecot/local.conf
    
    • 設定内容は以下の通り
      protocols = imap lmtp
      
      ssl_cert = </etc/ssl/dovecot/server.cer
      ssl_key = </etc/ssl/dovecot/server.key
      
      # Services
      service lmtp {
       unix_listener /var/spool/postfix/private/dovecot-lmtp {
      	 group = postfix
      	 mode = 0600
      	 user = postfix
      	}
      }
      service imap-login {
      	inet_listener imap {
      		address = 0.0.0.0
      		port = 143
      	}
      	inet_listener imaps {
      		address = 0.0.0.0
      		port = 993
      	}
      }
      service imap {
      }
      service auth {
      	unix_listener /var/spool/postfix/private/auth {
      		group = postfix
      		mode = 0660
      		user = postfix
      	}
      	user = doveauth
      }
      service auth-worker {
       user = doveauth
      }
      verbose_proctitle = yes
      
      # Storage
      mail_location = maildir:~/maildir
      mail_plugins = acl quota
      
      # Protocol
      protocol lmtp {
      	postmaster_address = xxx@xxxx.xx   # required
      	mail_plugins = quota sieve
      }
      protocol imap {
      	mail_plugins = $mail_plugins imap_acl imap_quota mail_log notify
      }
      
      # Authentication
      auth_mechanisms = plain
      passdb {
      	driver = passwd-file
      	args = username_format=%u /var/vmail/auth.d/%d/passwd
      }
      userdb {
      	driver = passwd-file
      	args = username_format=%u /var/vmail/auth.d/%d/passwd
      }
      
      plugin {
      	quota = dict:user::file:%h/maildir/dovecot-quota
      	quota_rule = *:storage=1GB
      	quota_rule2 = Trash:storage=+10%%
      	acl = vfile:/var/vmail/conf.d/%d/acls:cache_secs=300
      }
      # for mail filtering
      plugin {
      	sieve = ~/.dovecot.sieve
      	sieve_dir = ~/sieve
      	sieve_global_dir = /var/vmail/conf.d/%d/sieve
      	sieve_before = /etc/dovecot/sieve/rspam_deliver.sieve
      }
      
    • 上記で使ったrspam_deliver.sieveを作る
      mkdir /etc/dovecot/sieve
      vi /etc/dovecot/rspam_deliver.sieve
      
      • rspam_deliver.sieveの内容は以下の通り
        require "fileinto";
        require "imap4flags";
        
        if header :is "X-Spam" "Yes" {
        		fileinto "Junk";
        		setflag "\\seen";
        		stop;
        }
        
    • それをコンパイルしておく
      sievec /etc/dovecot/rspam_deliver.sieve
      

Rspamd

  • 次のサイトを参考としております。
  • DKIMキーを生成
    rspamadm dkim_keygen -s 'miimou' -d xxxx.xx > /etc/rspamd/local.d/dkim_priv.key
    chown rspamd /etc/rspamd/local.d/dkim_priv.key
    chmod 600 /etc/rspamd/local.d/dkim_priv.key
    vi /etc/rspamd/local.d/dkim_priv.key
    # -----END PRIVATE KEY-----より後をコピーしてから削除
    vi /etc/rspamd/local.d/dkim_pub.key
    # コピーした内容を貼り付け
    
  • この/etc/rspamd/local.d/dkim_pub.keyの内容は少し変更してDNSにも入れる
    • DNSサーバに入って

      vi /etc/dnsmasq.d/local.conf
      
    • 以下を追記(公開鍵なので隠す必要はないが,長いので省略)

      txt-record=miimou._domainkey.xxxx.xx,"v=DKIM1; k=rsa; p=xxxx"
      
  • local.dとoverride.dにファイルを配置する
    • local.d/antivirus.conf
      	clamav {
      		attachments_only = false;
      		servers = "/run/clamav/clamd.sock";
      	}
      
    • local.d/arc.conf
      	path = "/etc/rspamd/local.d/dkim_priv.key";
      	selector = "arc";
      	use_esld = false;
      
    • local.d/dkim_signing.conf
      path = "/etc/rspamd/local.d/dkim_priv.key";
      selector = "miimou";
      use_esld = false;
      
    • local.d/milter_headers.conf
      use = ["x-spamd-result","x-rspamd-server","x-rspamd-queue-id","authentication-results","x-spam-level","x-virus"];
      authenticated_headers = ["authentication-results","x-virus"];
      
    • local.d/redis.conf
      servers = "127.0.0.1";
      
    • local.d/statistic.conf
      autolearn = [-5, 10]
      
    • local.d/worker-controller.inc
      bind_socket = "0.0.0.0:11334";
      password = "$2$xxx$xxxxxxxx"
      enable_password = "$2$xxx$xxxxxxxx"
      
      • passwordの値は次のコマンドで生成する
        rspamadm pw
        
    • local.d/worker-normal.inc
      enabled = false;
      
    • local.d/worker-proxy.inc
      milter = yes;
      timeout = 120s;
      bind_socket = "/var/run/rspamd.sock mode=0666";
      upstream "local" {
      	default = yes;
      	self_scan = yes;
      }
      
    • override.d/metrics.conf
      actions {
      	add_header = 10;
      }
      

メールアカウントの用意

  • ディレクトリを作成
    mkdir /var/vmail
    
  • 認証設定
    mkdir -p /var/vmail/auth.d/xxxx.xx
    vi /var/vmail/auth.d/xxxx.xx/passwd
    
    • 内容はこんな感じ.issoはWebサーバ編で使うので用意
      xxx@xxxx.xx:$6$xxxx$xxxxxxxx:5000:5000::/var/vmail/xxxx.xx/xxx::userdb_quota_rule=*:storage=1G
      isso@xxxx.xx:$6$xxxx$xxxxxxxx:5000:5000::/var/vmail/xxxx.xx/isso::userdb_quota_rule=*:storage=32M
      
      • $6$xxxx$xxxxxxxxはパスワードハッシュ。次のコマンドで作成
        mkpasswd
        
  • メールディレクトリの用意
    mkdir -p /var/vmail/xxxx.xx/xxx/maildir
    mkdir -p /var/vmail/xxxx.xx/isso/maildir
    chown 5000 /var/vmail/xxxx.xx/xxx/maildir
    chown 5000 /var/vmail/xxxx.xx/isso/maildir
    

自動起動

  • clamd, dovecot, rspamd, freshclam, redis, postfix

Webサーバ

  • メールサーバ編でやったようにDNSサーバの参照設定を行う
  • apkで次をインストール
    • nginx, sqlite, uwsgi, uwsgi-python3, python3, python3-dev, py-virtualenv, alpine-sdk, linux-headers
  • とりあえずnginxを設定
    • /etc/nginx/conf.d/xxxx.xx(作成)
      server {
      	listen 80;
      	listen [::]:80;
      
      	location ~ ^/isso/(.*)$ {
      		include uwsgi_params;
      		uwsgi_pass 127.0.0.1:8080;
      		uwsgi_param SCRIPT_NAME /isso;
      		uwsgi_param PATH_INFO /$1;
      	}
      
      	root	/var/www/xxxx.xx;
      	index	index.html index.htm;
      	server_name xxxx.xx;
      }
      
    • コンテンツは/var/www/xxxx.xxに配置

Issoのインストール

  • Issoの公式の説明を参考にしております。

  • まずvirtualenvを用意して入る

    virtualenv /opt/isso
    source /opt/isso/bin/activate
    
  • Issoを入れる

    pip install isso
    
  • 設定ファイルを作る

    mkdir /etc/isso
    vi /etc/isso/isso.conf
    
    • 設定する
      [general]
      dbpath = /opt/isso/var/comments.db
      host = http://xxxx.xx/
      max-age = 15m
      notify = smtp
      
      [moderation]
      enabled = true
      
      [smtp]
      username = isso@xxxx.xx
      password = xxxx
      host = mail
      port = 587
      security = starttls
      to = xxx@xxxx.xx
      from = xxx@xxxx.xx
      timeout = 10
      
  • uWSGIの設定を作成する

    vi /etc/uwsgi/conf.d/isso.ini
    
    • 設定内容は以下の通り
      [uwsgi]
      socket = 127.0.0.1:8080
      master = True
      ;
      processes = 1
      cache2 = name=hash,items=1024,blocksize=32
      ;
      spooler = /opt/isso/var/mail
      plugin = python3
      module = isso.run
      ;
      virtualenv = /opt/isso
      env = ISSO_SETTINGS=/etc/isso/isso.conf
      
  • メールサーバのPostfixの証明書をコピーしてきて/usr/local/share/ca-certificates/mail-smtp.crtに配置(ホスト側で)

    scp mail:/etc/ssl/postfix/server.cer tmp_201801_mail.crt
    scp tmp_201801_mail.crt exserv:/usr/local/share/ca-certificates/mail-smtp.crt
    
  • 読み込ませる

    update-ca-certificates
    
  • データ置き場を作る

    dir /opt/isso/var
    own isso:isso /opt/isso/var
    

自動起動

  • nginx, uwsgi, uwsgi.isso

結び

この記事では本サーバの構築手順について記しました。 これは備忘録として残すものですから、 各自環境に応じてアレンジしてみてください。