Ubuntu のパッケージリポジトリのミラーをローカルに建てたら幸せになった話

【修正 2013/08/04】 /etc/apt/mirror.list にミスが有りましたので修正しました。 修正前の記事では run_postmirror が 0 に設定されていましたが、これでは postmirror.sh が実行されません。

こんばんは yosida95 です

いきなりですが、ぼくの部屋では10台(物理・仮想あわせて)の Ubuntu Server が常に動いています。 また、実験用として使う一時的な仮想マシンにも大抵の場合、 Ubuntu Server をインストールしています。 なお、よしだ VPS では OS の選択肢として Ubuntu Server 12.04 LTS に対応しています。 (昔は RHEL クローンの Scientific Linux を愛用していたのですが、どうしても Linux Kernel のバージョンが古いので、そこそこ新しいバージョンに追随している Ubuntu Server を使っている状況です。)

さて、このように10台以上の Ubuntu をコンスタントに運用していてストレスを感じることの1つに パッケージのアップグレードやインストールの待ち時間があります。 アップグレードは自動でやっているのでそこまででも無いのですが、インストールの待ち時間はそこそこストレスが掛かります。

そこで一念発起して、ローカルにパッケージリポジトリのミラーを建てて、高速ダウンロードを可能にしてストレッサーを取り除こうとしたっていうワケです。

方法

$ sudo apt-get install apt-mirror
$ sudo apt-mirror

この2行だけです。 この2行を実行すると、パッケージのダウンロードが始まります。 ただし、 wget が20プロセス並列に。

大抵の場合、20スレッド並列に動くような CPU は自宅に無く、コンテキストスイッチが発生しまくりでオーバーヘッドが大きいし、ロードアベレージは上がりまくって良いこと無いです。 また、ダウンロード元は archive.ubuntu.com で、ただでさえスループット伸びないわけです。

設定を変える

そこで、設定を変更する必要があります。 設定ファイルは /etc/apt/mirror.list にあります。 設定方法はみれば大体わかると思います。 以下にぼくが実際に使っている設定を載せます。

############# config ##################
#
set base_path         /var/spool/apt-mirror
#
set mirror_path       $base_path/mirror
set skel_path         $base_path/skel
set var_path          $base_path/var
set cleanscript       $var_path/clean.sh
set defaultarch       i386
set postmirror_script $var_path/postmirror.sh
set run_postmirror    0
set nthreads          4
set _tilde            0
#
############# end config ##############

deb-i386 http://ftp.jaist.ac.jp/ubuntu precise main restricted universe multiverse
deb-i386 http://ftp.jaist.ac.jp/ubuntu precise-updates main restricted universe multiverse
deb-i386 http://ftp.jaist.ac.jp/ubuntu precise-backports main restricted universe multiverse
deb-i386 http://ftp.jaist.ac.jp/ubuntu precise-security main restricted universe multiverse
deb-i386 http://ftp.jaist.ac.jp/ubuntu precise-proposed main restricted universe multiverse

deb-amd64 http://ftp.jaist.ac.jp/ubuntu precise main restricted universe multiverse
deb-amd64 http://ftp.jaist.ac.jp/ubuntu precise-updates main restricted universe multiverse
deb-amd64 http://ftp.jaist.ac.jp/ubuntu precise-backports main restricted universe multiverse
deb-amd64 http://ftp.jaist.ac.jp/ubuntu precise-security main restricted universe multiverse
deb-amd64 http://ftp.jaist.ac.jp/ubuntu precise-proposed main restricted universe multiverse


deb-src http://ftp.jaist.ac.jp/ubuntu precise main restricted universe multiverse
deb-src http://ftp.jaist.ac.jp/ubuntu precise-updates main restricted universe multiverse
deb-src http://ftp.jaist.ac.jp/ubuntu precise-backports main restricted universe multiverse
deb-src http://ftp.jaist.ac.jp/ubuntu precise-security main restricted universe multiverse
deb-src http://ftp.jaist.ac.jp/ubuntu precise-proposed main restricted universe multiverse


clean http://ftp.jaist.ac.jp/ubuntu
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise/main/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise/restricted/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise/universe/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise/multiverse/i18n/

skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-updates/main/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-updates/restricted/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-updates/universe/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-updates/multiverse/i18n/

skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-backports/main/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-backports/restricted/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-backports/universe/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-backports/multiverse/i18n/

skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-security/main/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-security/restricted/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-security/universe/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-security/multiverse/i18n/

skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-proposed/main/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-proposed/restricted/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-proposed/universe/i18n/
skip-clean http://ftp.jaist.ac.jp/ubuntu/dists/precise-proposed/multiverse/i18n/

1つ特徴としては、 deb-i386 や deb-amd64 などと、デフォルトの設定と異なる設定をしています。 これは10台のサーバーにインストールしたアーキテクチャが統一されていなく、 i386 と amd64 両方のバージョンのパッケージが必要なためです。

また、ダウンロード元は、 jp.archive.ubuntu.com でも良いと思いますが、理研や jaist の方が多分スループットが伸びます。 日本国内のミラーサーバー一覧からネットワーク的に近く、帯域の太いものを選べば幸せになると思います。

定期的にパッケージを更新する

cron で apt-mirror を回すだけです。 apt-mirror をインストールすると、 /etc/cron.d/apt-mirror に毎日4時に cron をするための設定がコメントアウトされた状態で書かれているので、コメントアウトを外して、都合の良いタイミングで同期が取れるように設定を変更して下さい。

HTTP サーバーを建てる

apt は HTTP でパッケージをダウンロードしてくるので、 HTTP サーバーを建てないと、 apt-mirror がダウンロードしてきたパッケージ達はただのストレージ潰しとなってしまいます。 そこで、 HTTP サーバーを建てて、他の Ubuntu がアクセスできるようにします。

なお、 HTTP サーバーは Apache でも Nginx でも Lighttpd でもよいと思いますが、ここではぼくの個人的な趣味で Nginx を入れて設定したいと思います。 本当なら、ソースコードをダウンロードしてきて、必要な機能だけを持つ Nginx をビルドして使うところですが、その手順を紹介すると1本の独立した記事が出来そうなので、 apt-get で全部入りの Nginx を入れてしまいます。

$ sudo apt-get install nginx

設定ファイルは /etc/nginx にあります。 まずは、 nginx.conf を開いて、 worker_processes や worker_rlimit_* や、 worker_connections を適切な値に変更します(この手順は省いても問題有りませんが、この設定をすることでよりパフォーマンスが伸びる場合があります)。

次に、 /etc/nginx/sites-available に apt-mirror などという分かりやすい名前で apt-mirror ようの設定ファイルを作り、最低以下の内容を記述します。

server {
    server_name ${host_name};
    listen            80;

    location /ubuntu {
        root /var/spool/apt-mirror/mirror/${ダウンロード元のホスト名};
        autoindex on;
    }
}

これができたら、 /etc/nginx/sites-enabled に、今作った設定ファイルへのシンボリックリンクを張って、 Nginx を起動します。

$ ln -s /etc/nginx/sites-available/apt-mirror /etc/nginx/sites-enabled
$ sudo service nginx start

Ubuntu の apt が、今回建てたミラーサーバーからパッケージを取得するようにする

/etc/apt/sources.list に、パッケージの取得先の URI が記述されているので、これを今回建てたミラーサーバに変更します。

deb http://ubuntu.mirror.yosida95.com/ubuntu/ precise main restricted universe multiverse
deb-src http://ubuntu.mirror.yosida95.com/ubuntu/ precise main restricted universe multiverse

deb http://ubuntu.mirror.yosida95.com/ubuntu/ precise-updates main restricted universe multiverse
deb-src http://ubuntu.mirror.yosida95.com/ubuntu/ precise-updates main restricted universe multiverse

deb http://ubuntu.mirror.yosida95.com/ubuntu/ precise-backports main restricted universe multiverse
deb-src http://ubuntu.mirror.yosida95.com/ubuntu/ precise-backports main restricted universe multiverse

deb http://ubuntu.mirror.yosida95.com/ubuntu precise-security main restricted universe multiverse
deb-src http://ubuntu.mirror.yosida95.com/ubuntu precise-security main restricted universe multiverse

※なお、これらの URI は実際にぼくのサーバーで使っているものですが、外部からはアクセス出来ないようにしています。

i18n 対応する

この状態で、 apt-get update をすると分かるのですが、以下の様なログが出力されます。

(無視|Ign) http://ubuntu.mirror.yosida95.com precise/main Translation-en
(無視|Ign) http://ubuntu.mirror.yosida95.com precise/restricted Translation-en
(無視|Ign) http://ubuntu.mirror.yosida95.com precise/universe Translation-en
(無視|Ign) http://ubuntu.mirror.yosida95.com precisemultiverse Translation-en
(無視|Ign) http://ubuntu.mirror.yosida95.com precise/main Translation-ja
(無視|Ign) http://ubuntu.mirror.yosida95.com precise/restricted Translation-ja
(無視|Ign) http://ubuntu.mirror.yosida95.com precise/universe Translation-ja
(無視|Ign) http://ubuntu.mirror.yosida95.com precisemultiverse Translation-ja
(無視|Ign) http://ubuntu.mirror.yosida95.com precise/main TranslationIndex
(無視|Ign) http://ubuntu.mirror.yosida95.com precise/restricted TranslationIndex
(無視|Ign) http://ubuntu.mirror.yosida95.com precise/universe TranslationIndex
(無視|Ign) http://ubuntu.mirror.yosida95.com precisemultiverse TranslationIndex

これは、 i18n 系のパッケージが apt-mirror ではダウンロードされないため、 404 Not Found が返っているためです。 これを修正するためには、 i18n 系のパッケージを手動でダウンロードしてくれば良いわけです。

apt-mirror によるパッケージのダウンロードが終わった後に、/var/spool/apt-mirror/var/postmirror.sh というスクリプトが実行されます。 このフックスクリプトに i18n 系のパッケージをダウンロードするコードを書いてやればいいわけです。

#!/bin/bash

RSYNC="rsync --recursive --times --links --hard-links --delete --delete-after"
SOURCE="rsync://ftp.jaist.ac.jp/pub/Linux/ubuntu"
TARGET="/var/spool/apt-mirror/mirror/ftp.jaist.ac.jp/ubuntu"

dists=(precise precise-updates precise-backports precise-security)

for dist in "${dists[@]}"; do
    ${RSYNC} ${SOURCE}/dists/${dist}/main/i18n/ ${TARGET}/dists/${dist}/main/i18n/
    ${RSYNC} ${SOURCE}/dists/${dist}/multiverse/i18n/ ${TARGET}/dists/${dist}/multiverse/i18n/
    ${RSYNC} ${SOURCE}/dists/${dist}/restricted/i18n/ ${TARGET}/dists/${dist}/restricted/i18n/
    ${RSYNC} ${SOURCE}/dists/${dist}/universe/i18n/ ${TARGET}/dists/${dist}/universe/i18n/
done

※ぼくがダウンロード元として使っている jaist は rsync でもアクセスできるようになっているので、ここでは rsync で同期をとるようにします。 $SOURCE や $TARGET を選んだミラーサーバーに合わせて適切に変更して下さい。

以上です

お疲れ様でした。

この設定により、パッケージのアップデートやインストールにかかる時間は劇的に短縮されてストレスが軽減しました。 ぼくはこのミラーサーバーのために、よしだ VPS 上に新しいインスタンスを切ったのですが、その OS のサイズとダウンロードしてきたパッケージのサイズ合わせてわずか 136GiB 程度のストレージを使うだけでこのように快適な環境を手に入れられたので、とても幸せになりました。