カテゴリー: サーバー管理

  • WSLを使ってメーリングリストを作成(番外編)

     実験環境で動作確認した後、本番環境で動かそうとしたところ、次々とトラブルに見舞わされた。

    1. Lightsailで動いていたインスタンスが、Windows Server 2016であった。
      WSLが対応していない。
    2. LightsailのインスタンスをWindows Server 2019にしたが、WSLが古くて、WSLバージョン2が動作しない。
    3. 旧バージョンのwsl.exeは仕様が違って、バックアップ、リストアができないらしい。

    Lightsailインスタンスのバージョンアップ

    ・元サーバーの更新
    OS,squid,win-acme,xampp,wordpressなどすべてのモジュールを最新にする。
    1度目は、OSのバージョンアップに合わせて、各モジュールが更新されていたので、変動パラメーターが多すぎて問題の原因が絞り込めなかった。
    また、xamppはPHP7.4系とした。8系は変更が多くて問題点が絞り込めず、ダウンロード数の多い7系にした。

    ・移行準備
    タスクスケジューラーに追加したタスクをエクスポートしておく

    ・インスタンスの設定
    新しいバージョンのインスタンスを作成する
    静的IPを作成して新しいインスタンスにアタッチする
    Lightsailコンソールのファイアウォールを忘れずに。ファイアウォールはインスタンスごとに設定する
    ローカルIPのアドレスで相互に共有フォルダーC$をマウントしておく
    \172.26.xx.xx\C$

    ・OSの設定
    7-Zip、sskuraエディター、WinMergeのインストール
    WinMwegeの最新版は2.16.18だったが、フォルダー展開時にカーソルが先頭に移動する不具合があるため2.16.16をインストールした。
    システム環境変数
    PATHに C:\xampp\ImageMagick\bin を追加
    WORDPRESS_BACKUPを環境に合わせて作成

    ・squidのインストール
    前と同じくサービスでは稼働させず、タスクスケジューラーで起動時に実行させる
    以下のコマンドで、キャッシュ用のフォルダーを作成させる必要がある。
    cd C:\Squid\var\cache\squid ; C:\squid\bin\squid.exe -z -F

    ・xampp
    PHPバージョンが7.4.xのを選んでインストールする。
    htdoc以下は、元サーバーからコピーする。
    mysqlはdata以下をそのままコピーした。

    ・wordpress
    そのままコピーして動作した

    ・win-acme
    サーバー移行手段が、ホームページにMigrationとして記述がある。
    https://www.win-acme.com/manual/migration
    暗号化されている設定ファイルを元サーバーで復号化し、新サーバーでサーバーの暗号化機能を使って暗号化すればいいらしい。

    サーバー証明書を移転する方法
    単純にコピーするだけでは、以下のエラーが出て、Orders下のファイルが削除されてしまう。
    [EROR] Unable to decrypt configuration value, may have been written by a different machine.
    メインメニューで、O ;More options…、M: Enctypt/decrypt configurationを選ぶと、以下のメッセージが表示されるのでそれに従って移行作業を行う。

    1.古いマシンで、EncryptConfig設定をfalseに設定する
    C:\xampp\tools\win-acme\settings.json のEncryptConfigをtrueからfalseにする
    
    2.win-acmeの設定ファイルを復号化する
    win-acme.exeのメインメニューから、o m と入力し、yを入力する
    この時、without encryptionとなっていることを確認する
    Current EncryptConfig setting: False
    Save all renewal files without encryption? (y/n) - yes 
    
    3.データファイルを新しいマシンにコピーする
    %ProgramData%\win-acme\ および settings.jsonを含むwin-acmeのフォルダーをコピーする
     謎だったSecret.jsonというファイルが作成されているので、一緒にコピーしておく 
    
    4.新しいマシンで、EncryptConfig設定をtrueに設定する C:\xampp\tools\win-acme\settings.json のEncryptConfigをfalseからtrueにする 
    
    5.win-acmeの設定ファイルを暗号化する
    win-acme.exeのメインメニューから、o m と入力し、yを入力する
     この時、with encryptionとなっていることを確認する
     Current EncryptConfig setting: True Save all renewal files with encryption? (y/n) - yes
    
    6.サーバー証明書の更新を行う
    win-acmeでの証明書更新予定がこの日からにリセットされる。そのため、証明書の期限までに更新されないことがあるので、必ず更新を行う

    WSLのインストール

    参考にしたページ

    ttps://docs.microsoft.com/en-us/windows/wsl/install-manual

    サーバーマネージャーで機能-Windows Subsystem for Linuxを有効にする

    管理者権限でPowerShellを開き、以下を実行する

    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

    Windowsを再起動する

    以下から、WSLの更新プログラムをダウンロードして実行する
    https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

    ディストリビューションをダウンロードする
     以下のリンクの下の方にあるDownloading distributionsのところにあるリンクからUbuntuののディストリビューションファイルをダウンロードする。
    https://docs.microsoft.com/en-us/windows/wsl/install-manual

    ダウンロードしたCanonicalGroupLimited.UbuntuonWindows_2004.2021.825.0.AppxBundleを
    そのまま7-Zipで開く。開けないときは拡張子をzipに変えてから開く。

    その中にある以下のファイルをC;\WSLに展開する。

    Ubuntu_2004.2021.825.0_x64.appx

    C:\WSL\Ubuntu\Ubuntu.exeを実行する。

    インストールが始まり、しばらくするとユーザー名を聞いてくる。

    ・アンインストール

    wslconfig.exe でディストリビューションUbuntuを削除する
    WSLの更新プログラムをプログラムと機能からアンインストールする
    管理者権限でPowerShellを開き、以下を実行する

    Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

    サーバーマネージャーではWindows Subsystem for Linuxを無効にできないみたい
    C:\WSL\Ubuntuを削除する
     削除できないフォルダーが残ったら、DOSデバイスパス指定で削除する

    ・Ubuntu設定

    viで画面が真っ黒になった。

    ターミナルタイプが環境変数TERMに設定されている
     $ env TERM=xterm-256color 
    デフォルトのansiに変えておくように.bash_aliasesに追加しておく
       export TERM=ansi

    ・バックアップ/リストア

    wsl.exeには機能が存在しないらしい。

    C:\WSL\Ubuntuを丸ごとバックアップ、削除してコピーすれば行けるかもしれない。行けないかもしれない。

    戻すときは、welconfig.exe でディストリビューションUbuntuを削除するしてからやるといいかもしれない。

    動作

    まだ長時間動かしたわけではないが、バックアップやリストアができないだけで、mailmanの動作自体には問題が無く、メーリングリストが運用できているようだ。

  • WSLを使ってメーリングリストを作成(自動起動)

     いくつかのプロセスは、Ubuntuが起動されるごとに実行しないといけない

     WSLが起動すると、必ずデフォルトユーザーがログインするので、デフォルトユーザーの.bash_aliasesで実行させることにした

      $ vi ~/.bash_aliases
    
    tty
    if [ "$REMOTEHOST" == "" ] && ) [ "`tty`" == "/dev/tty1" ] || [ "`tty`" == "/dev/pts/0" ] ); then
    #                                                  WSL 1                         WSL 2
        # start daemon
        sudo /etc/init.d/rsyslog status          || sudo /etc/init.d/rsyslog start
        sudo /etc/init.d/cron status             || sudo /etc/init.d/cron start
        test -f /var/run/inetd.pid               || sudo /etc/init.d/inetutils-inetd start 
        sudo /etc/init.d/postfix status          || sudo /etc/init.d/postfix start 
        sudo /etc/init.d/apache2 status          || sudo /sbin/apache2ctl start 
        sudo /bin/mkdir -p /var/lock/mailman
        sudo /bin/chown www-data:list /var/lock/mailman
        sudo /bin/chmod g+w /var/lock/mailman
        sudo /bin/mkdir -p /var/run/mailman
        sudo /bin/chown list /var/run/mailman
        sudo /bin/chmod g+w /var/run/mailman
        test -f /var/run/mailman/mailman.pid     || sudo /sbin/mailmanctl start 
        test -f /var/run/fetchmail.pid           || sudo /usr/bin/fetchmail --nosslcertck -f /root/.fetchmailrc
        ps -ef | grep -vw "$USER" | grep -w fetchmail_time || sudo /root/fetchmail_time.sh &
    
        sleep 2
    #    /usr/local/bin/port-forward.sh
        ps ax
        sudo /bin/apt update
    else
        LOGS=(/var/log/fetchmail.log /var/log/mail.log /var/log/mailman/post /var/log/apache2/access.log)
    
        for L in ${LOGS[@]} ; do
            if [[ ! `ps -ef | grep -vw "$USER"` =~ $L ]]; then
                echo sudo tail -F $L
                     sudo tail -F $L
                break
            fi
        done
    fi

    if文の後半はtelnetで接続された順番にログファイルを自動的に表示させている。

    ただし、sudoで実行させているため、パスワードを入力しなくても実行できるようにしておく

        $ sudo vi /etc/sudoers.d/auto-start
    %sudo ALL=NOPASSWD: /etc/init.d/apache2
    %sudo ALL=NOPASSWD: /etc/init.d/cron
    %sudo ALL=NOPASSWD: /etc/init.d/inetutils-inetd
    %sudo ALL=NOPASSWD: /etc/init.d/postfix
    %sudo ALL=NOPASSWD: /etc/init.d/rsyslog
    %sudo ALL=NOPASSWD: /sbin/apache2ctl
    %sudo ALL=NOPASSWD: /sbin/mailmanctl
    %sudo ALL=NOPASSWD: /sbin/service
    %sudo ALL=NOPASSWD: /bin/apt
    %sudo ALL=NOPASSWD: /bin/chmod
    %sudo ALL=NOPASSWD: /bin/chown
    %sudo ALL=NOPASSWD: /bin/ln
    %sudo ALL=NOPASSWD: /bin/ls
    %sudo ALL=NOPASSWD: /bin/mkdir
    %sudo ALL=NOPASSWD: /usr/bin/fetchmail
    %sudo ALL=NOPASSWD: /usr/bin/vi
    %sudo ALL=NOPASSWD: /usr/bin/vim
    %sudo ALL=NOPASSWD: /usr/bin/view
    %sudo ALL=NOPASSWD: /usr/bin/less
    %sudo ALL=NOPASSWD: /usr/lib/mailman/bin/dumpdb
    
        $ sudo chmod 0440 /etc/sudoers.d/auto-start

    ポート番号の変更

    すでにホストマシンでtelnetdやxampp内のapacheが起動しているときはWSLのポート番号を変えることで共存させる。
    なお、10080は最近のWebブラウザーではアクセスできないようにされているようで(ERR_UNSAFE_PORTというエラーが表示される)、他のポートを選ぶ。

    telnetd
      $ sudo vi /etc/services
    telnet		23/tcp
      ↓
    telnet		9023/tcp
    apache2
      $ sudo vi /etc/apache2/sites-available/000-default.conf
    <VirtualHost *:80>
      ↓
    <VirtualHost *:9080>
    
      $ sudo vi /etc/apache2/ports.conf
    Listen 80
      ↓
    Listen 9080
      postfix
        $ sudo vi /etc/postfix/master.conf
    smtp      inet  n       -       y       -       -       smtpd
      ↓
    #smtp      inet  n       -       y       -       -       smtpd
    9025      inet  n       -       y       -       -       smtpd
    mailman
      $ sudo vi /etc/mailman/mm_cfg.py
    DEFAULT_URL_PATTERN = 'http://%s/mailman/'
     ↓
    DEFAULT_URL_PATTERN = 'http://%s:9080/mailman/'
    
    add_virtualhost(VIRTUAL_URL_HOST2, VIRTUAL_EMAIL_HOST2)
     ↓
    add_virtualhost(VIRTUAL_URL_HOST2, VIRTUAL_EMAIL_HOST2)
    SMTPHOST = 'ml.mydomain.com'
    SMTPPORT = 9025
      fetchmail
        $ sudo vi /root/.fetchmailrc
    smtphost ml.mydomain.com/9025

    利用しているポート番号の確認

      $ sudo ss -natup

    ポートマップ

    WSL2のプライベートアドレスは起動するごとに変わる。そのため、外部からWebブラウザーや、telnetで接続できるようにするには、WSL2のポートをホストマシンのポートに接続するスクリプトを実行する。

    WSL内で実行してもよいが、ファイアウォールの設定もあるのでWindows側から行う。

    WSLのバージョンが1の場合は、ファイアウォールやポートフォワードを削除する。

    wsl_port.ps1
    -----
    if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole("Administrators")) { Start-Process powershell.exe "-File `"$PSCommandPath`"" -Verb RunAs; exit }
    
    # All the ports you want to forward separated by comma
    $ports=@(9023, 9025, 9080);
    $ports_a = $ports -join ",";
    
    # Remove Firewall Exception Rules
    try {
    # 初回やWSLのバージョンを1から2にした場合はエラーが出るが、無視してよい
      iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -ErrorAction Ignore";
    } catch {
    }
    
    $ip = bash.exe -c "ip r |tail -n1|cut -d ' ' -f9"
    # ipアドレスが取得できないときはWSL2ではないとみなしポートフォワードを削除する
    if ([string]::IsNullOrEmpty($ip)) {
      foreach ($port in $ports) {
        iex "netsh.exe interface portproxy delete v4tov4 listenport=$port listenaddress=*" > $null;
      }
    
    } else {
      # Adding Exception Rules for inbound and outbound Rules
      iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";
      iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_a -Action Allow -Protocol TCP";
    
      foreach ($port in $ports) {
        iex "netsh.exe interface portproxy add v4tov4 listenport=$port listenaddress=* connectport=$port connectaddress=$ip";
      }
    }
    
    # Show proxies
    iex "netsh.exe interface portproxy show v4tov4";
    
    -----

    Windows起動時にWSLを起動する

    WSL-start.batのショートカットを”C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp”や、 “shell:startup”に置いておくと、Windowsが起動するタイミングでUbuntuを起動し、上のポートマップスクリプトも実行させる。

    WSL-start.bat  
    -----
    start %LOCALAPPDATA%\Microsoft\WindowsApps\ubuntu.exe
    timeout -t 20
    powershell -file wsl_port.ps1
    timeout /t 60 > nul
    -----

    参考:Windows WSL2に外部から直接アクセスするための設定

    https://rcmdnk.com/blog/2021/03/01/computer-windows-network/

    mailmanデータベースをバックアップする

      for /f "usebackq delims=" %%f in (`wsl.exe -- ls /var/lib/mailman/lists/`) do (
        wsl.exe -- sudo /usr/lib/mailman/bin/dumpdb /var/lib/mailman/lists/%%f/config.pck > C:\Temp\config.pck.%%f.txt
      )
    
  • WSLを使ってメーリングリストを作成(複数ドメイン)

     複数のドメインを運用しているため、mailmanをそれぞれのドメインでも動くようにする。

     postfix+mailmanで複数ドメインに対応する方法はいくつかるようだが、一番単純なメーリングリスト名は全ドメイン共通での設定にする。
     postfix-to-mailman.pyを使えば、配送経路などもちゃんと設定できるらしいが、今回はそこまでしない。

    ・MercuryMailの設定

    別ドメインのメーリングリストで使用するメールアカウントを作成する
    ユーザー名:mydomain2
    そのメールアカウントを、Configurationー”Mercury Core Module Configuration”ー”Local Domains” にドメインメールボックスとして追加する

    Core ModuleーLocal Domains
    追加
      ↓
    DM=mydomain2 ml.mydomain2.net

    ・postfixの設定

     変更なし

    ・mailmanの設定

     別ドメインを仮想ホストとして登録する。

      $ sudo vi /etc/mailman/mm_cfg.py
    DEFAULT_EMAIL_HOST = 'ml.mydomain.com'
     ↓
    DEFAULT_EMAIL_HOST = 'ml.mydomain.com'
    VIRTUAL_EMAIL_HOST1 = 'ml.mydomein2.net'
    
    DEFAULT_URL_HOST   = 'ml.mydomain.com'
     ↓
    DEFAULT_URL_HOST   = 'ml.mydomain.com'
    VIRTUAL_URL_HOST1 = 'ml.mydomain2.net'
    
    POSTFIX_STYLE_VIRTUAL_DOMAINS = [DEFAULT_EMAIL_HOST]
    add_virtualhost(DEFAULT_URL_HOST, DEFAULT_EMAIL_HOST)
     ↓
    POSTFIX_STYLE_VIRTUAL_DOMAINS = [DEFAULT_EMAIL_HOST, VIRTUAL_EMAIL_HOST1]
    add_virtualhost(DEFAULT_URL_HOST, DEFAULT_EMAIL_HOST)
    add_virtualhost(VIRTUAL_URL_HOST1, VIRTUAL_EMAIL_HOST1)

    ・fetchmailの設定

    ml.mydomain2.netのメールをポーリングするよう追加する。

        $ sudo vi /root/.fetchmailrc
    poll mail.mydomain.com with proto imap envelope "X-Envelope-To"
      localdomains ml.mydomain2.net 
      user "mydomain2" with pass "mailパスワード" to * here

    複数ドメインであっても一つのメールボックスで処理するときは、以下のように記述する

    poll mail.mydomain.com with proto imap envelope "X-Envelope-To"
      localdomains ml.mydomain.com ml.mydomain2.net 
      user "mydomain" with pass "mailパスワード" to * here

    ・注意

     メーリングリストの全体的オプションで、メールの送信に使うホスト名(ドメイン名)を変更した場合に、/var/lib/mailman/data/virtual-mailmanが更新されなかったので、以下のコマンドで強制的に更新する必要があった。

        $ sudo /usr/lib/mailman/bin/genaliases