paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

ConnectBotでAndroidの簡易VPNを作る

ブログでちょこちょこ紹介しているFirefly iiiですが、いい加減外出先からでも操作したくなりました。

個人の資産情報が入っており、Internetに直接公開するのは危ないのでVPNを張ってアクセスしたいと思います。

Team viewerとかGoogle desktopを使えば簡単ですが、それだと面白くないのでNWエンジニアらしくVPNを張ることにしました。

VPNの選択肢

ぱっと浮かぶ選択肢としては

  1. ローカルサーバにVPNサーバを構築する
  2. ルータにVPNサーバを構築する
  3. SSHポートフォワーディングを使う

とありますが、今回は環境の都合上3を選択しました。
ルータはISPのレンタルルータなのですが、いろいろできない事が多かったためです。

  1. ルータのポートフォワーディングが効かない
    • TCPはポートフォワーディングできるのですが、なぜかUDPはできませんでした。設定上は選択できるのに...
  2. ルータにVPNサーバ機能が無かった
    • VPNクライアントのみでした。

ということでルータがポートフォワーディングでき、VPNということでSSHのポートフォワーディングを使うことにしました。

環境

こんな感じです。
流石にsshポートをそのまま公開するのも何なので気持ち番号を変更しました。

f:id:paloma69:20210822200345p:plain

各環境の設定は以下の通りです。

Android

ポートフォワーディングできるSSHクライアントアプリを探したらConnectBotが良さそうだったのでこれにしました。

ConnectBot - Home

設定画面はこんな感じです。

f:id:paloma69:20210822200417p:plain

SSHのポート変更もできるし、シェルセッションを使わないという事もできます。(ポートフォワードのみ)
公開鍵も作成できて結構いいアプリですね。

ローカルポートの8000番をUbuntuフォワーディングします。
リモートフォワードだとサーバが転送用IPをlocalhostでListenしてしまう様なので、ひと手間加えるくらいならということでローカルフォワードにしました。

RT

TCPのポートフォワーディングのみ行います。

12345番ポートを22番に変換します。
これだけ。

Ubuntu

このブログでもよく出てくるサブ機です。
FireflyはこのマシンのLXD内にありますが、ホストの80ポートにアクセスすればそのままProxyでFireflyにアクセスできます。

sshdは公開鍵認証のみにしてあるので、突破は至難の業ですよ。

アクセスしてみます

ConnectBotの起動

作成済みの接続を起動します。

f:id:paloma69:20210822200502p:plain

シェルターミナルは起動してないので画面は何も表示されません。

f:id:paloma69:20210822200519p:plain

Fireflyへアクセス

ローカルIPの8000へアクセスします。
先にこっちをスクショ取ったので時刻はお気になさらず。
ログイン画面は割愛しますが、無事にログインできました!
ConnectBotがアクティブのタスクじゃなくてもちゃんと動いてくれてますね。

ちなみにこの8000番はsshで包まれているのでキャプチャしても発見できません。

f:id:paloma69:20210822200809p:plain

f:id:paloma69:20210822200818p:plain

いいですね、ちゃんとデータが見えます。

ちなみにlocalhostだと表示されません。

f:id:paloma69:20210822200849p:plain

Androidの各ファイルをちゃんと見たことありませんが、hostsに書かれてないんでしょうね。

まとめ

今回は環境の制約でSSHポートフォワードを使ったVPN環境を作りました。
これで外出先からすぐに家計簿をつけられるようになりましたw

SSHポートフォワードはお手軽なVPNで良いですが、単体へのアクセスしかできないので、やはりいつかはIPsecあたりでちゃんとしたVPNを作りたいですね。

初めてpythonのpdbでデバッグをやってみた

前の映画情報取得ツールを製作していた時のこと。

OMDB APIを取得するツールをpythonで自作する - paloma blog

全処理を一旦書き上げたのですが実行しても出力されません。

(movies) masashi@PC-ubuntu:~/tests$ python getinfo.py 
(movies) masashi@PC-ubuntu:~/tests$ 

しかしプロンプト内でやるとちゃんと返ってきます。

>>> main()

Title: Argo
Year: 2012
Rated: R
Released: 12 Oct 2012
Runtime: 120 min

どうにもわからないのでデバッグをすることにしました。

pdbモジュール

よくやるデバッグと言えばprintを仕込んで変数内容を確認するというものですが、
私もpython歴数年になりますのでそろそろデバッグもスマートに行いたいところです。

pdbモジュールの記事がよく出てくるのでこちらを使ってデバッグしてみます。

pdb --- Python デバッガ — Python 3.9.4 ドキュメント

モジュール読み込み

コードの中に仕込む方法が公式ドキュメントなどで出てきますが、引数で読み込ませる方法のほうが簡単そうだったのでこちらで試してみます。

-m pdbでモジュールを読み込ませてコードを起動します。

(movies) masashi@PC-ubuntu:~/tests$ python -m pdb getinfo.py
> /home/masashi/tests/getinfo.py(1)<module>()
-> import requests
(Pdb) 

するとこんな感じでpdbの対話モード入ります

ヘルプ

(Pdb) h

Documented commands (type help <topic>):
========================================
EOF    c          d        h         list      q        rv       undisplay
a      cl         debug    help      ll        quit     s        unt      
alias  clear      disable  ignore    longlist  r        source   until    
args   commands   display  interact  n         restart  step     up       
b      condition  down     j         next      return   tbreak   w        
break  cont       enable   jump      p         retval   u        whatis   
bt     continue   exit     l         pp        run      unalias  where    

Miscellaneous help topics:
==========================
exec  pdb

pdbを使うのに戸惑う理由がオプションの多さだと思います。
どれを使えばよいか迷いますが、とりあえずは変数が想定通り格納されているかという観点で考えると
p(rint)だけ使えばOKということになります。

ちなみコードはこちら

llで全行出力されます。
長文のコードだと使えないかもしれませんが今回のは短いです。

テスト用にちょっといじってあります。
実はこの時点でおかしいところがわかりますね。

(Pdb) ll
  1  ->   import requests
  2    import sys
  3    import json
  4    # import configure
  5    import re
  6    
  7    # KEY = configure.APIKEY
  8    # url = 'http://www.omdbapi.com/'
  9    # gettitle = '+'.join(sys.argv[1:])
 10    # getinfo = ''.join([url, '?apikey=', KEY, '&t=', gettitle])
 11    with open('sample.json', 'r') as f:
 12        movieinfo = f.read()
 13    
 14    def main():
 15    
 16        dataload = json.loads(movieinfo)
 17        datadump = json.dumps(dataload, indent=0)
 18    
 19        shapedata = re.sub('\n.\n|"|{|}|\[|\]', "", datadump)
 20        shapedata = re.sub(',\n', "\n", shapedata)
 21    
 22        print(shapedata)
 23    
 24    if __name__ == 'main':
 25        main()

ちなみにlだと現在の行周辺が出力されます。

-> import sys
(Pdb) l
  1    import requests
  2  ->   import sys
  3    import json
  4    # import configure
  5    import re
  6    
  7    # KEY = configure.APIKEY
  8    # url = 'http://www.omdbapi.com/'
  9    # gettitle = '+'.join(sys.argv[1:])
 10    # getinfo = ''.join([url, '?apikey=', KEY, '&t=', gettitle])
 11    with open('sample.json', 'r') as f:

n(ext)

nは1行ずつ読み込みます。
空エンターでも同じ挙動をしますね。

(Pdb) n
> /home/masashi/tests/getinfo.py(2)<module>()
(Pdb) n
> /home/masashi/tests/getinfo.py(3)<module>()
-> import json
(Pdb) 
> /home/masashi/tests/getinfo.py(5)<module>()
-> import re
(Pdb) 
> /home/masashi/tests/getinfo.py(11)<module>()
-> with open('sample.json', 'r') as f:
(Pdb) 
> /home/masashi/tests/getinfo.py(12)<module>()
-> movieinfo = f.read()
(Pdb) 
> /home/masashi/tests/getinfo.py(14)<module>()
-> def main():

p(rint)

pで変数を出力できます。
被疑の行まで来たらpで中身を確認すれば所謂printのデバッグになりますね。

今回はサンプルのjsonデータを読み込ませてますが、ちゃんと格納されてます。

(Pdb) p movieinfo
'{"Title":"Argo","Year":"2012","Rated":"R","Released":"12 Oct 2012","Runtime":"120 min","Genre":"Biography, Drama, Thriller","Director":"Ben Affleck","Writer":"Chris Terrio, Tony Mendez, Joshuah Bearman","Actors":"Ben Affleck, Bryan Cranston, John Goodman",
...

main実行の行まで来たのでここで手動で実行してみます。

> /home/masashi/tests/getinfo.py(24)<module>()->None
-> if __name__ == 'main':
(Pdb) main()

Title: Argo
Year: 2012
Rated: R
Released: 12 Oct 2012
Runtime: 120 min
...

ちゃんと出力できてますね。
となるとターミナルから起動、出力周りが怪しいということになりますね。

原因

 24  ->  if __name__ == 'main':
 25        main()

mainを実行されるときの行がミスしてました。

mainは__main__と書かないと認識されませんね。
ここは久しぶりに空で書いたのでルールを忘れてました。

というわけで対象行を修正して無事にデバッグ完了です。

 24  ->  if __name__ == '__main__':
 25        main()
(movies) masashi@PC-ubuntu:~/tests$ python getinfo.py

Title: Argo
Year: 2012
Rated: R
Released: 12 Oct 2012
Runtime: 120 min
...

おまけ r(eturn)

nだと1行ずつで時間がかかってしまいましが、rだと「現在の関数が返るまで実行を継続」する様です。
現在の関数が何を指しているか不明ですが私の場合だとmain関数のところまで飛びました。

-> import requests
(Pdb) l
  1  ->   import requests
  2    import sys
  3    import json
  4    # import configure
  5    import re
  6    
  7    # KEY = configure.APIKEY
  8    # url = 'http://www.omdbapi.com/'
  9    # gettitle = '+'.join(sys.argv[1:])
 10    # getinfo = ''.join([url, '?apikey=', KEY, '&t=', gettitle])
 11    with open('sample.json', 'r') as f:
(Pdb) r
--Return--
> /home/masashi/tests/getinfo.py(24)<module>()->None
-> if __name__ == 'main':
(Pdb) l
 19        shapedata = re.sub('\n.\n|"|{|}|\[|\]', "", datadump)
 20        shapedata = re.sub(',\n', "\n", shapedata)
 21    
 22        print(shapedata)
 23    
 24  ->   if __name__ == 'main':
 25        main()
[EOF]

まとめ

というわけで初めてpdbを使ったデバッグを行いました。
いつもprintを仕込んでいましたが、コードを汚さずにデバッグできるのは便利ですね。
とりあえずpだけ覚えておけば私の規模のコードだと問題なくできました。

pdbには他にもいろいろオプションがあるので、また詰まる時が来たら他のも使ってみたいと思います。
関数の中に入るコマンドもあった記憶がありますが、今回は確認できなかったので次回チャレンジですね。

OMDB APIを取得するツールをpythonで自作する

私の趣味の一つに映画鑑賞がありますが、視聴後はtwitterに映画情報を投稿して備忘としています。

情報の取得にはBash snippetsのmoviesコマンドを使っていたのですが、ある時取得できなくなってしまいました。

Bash-Snippets - Useful BASH Scripts For Heavy Commandline Users

masashi@PC-ubuntu:~$ movies sorry to bother you

==================================================
| Title: 
| Year: 
| Runtime: 
| Genre: 
| Director: 
| Actors: 
==================================================

この様に空の値が返ってきます。

ソースをみたところomdb apiというサイトのAPIを叩いているようですが、APIキーの期限が切れてしまったのでしょうか。

手動で投稿でもいいんですが、せっかく取得〜投稿までのツールを作ったので取得部分を自作したいと思います。

APIキー申請

一日1000アクセスまでなら無料の様です。
簡単に用途を書いて申請。

OMDb API - The Open Movie Database

取得ツール

映画のデータはjsonで取得できますが、moviesコマンドはある程度成形して出力してくれます。
どう加工しましょうかね。

  • 取得データ

ちょうど昨日見たのですがBad boysのデータを使います。

{"Title":"Bad Boys","Year":"1995","Rated":"R","Released":"07 Apr 1995","Runtime":"119 min","Genre":"Action, Comedy, Crime","Director":"Michael Bay","Writer":"George Gallo, Michael Barrie, Jim Mulholland","Actors":"Will Smith, Martin Lawrence, Lisa Boyle","Plot":"Two hip detectives protect a witness to a murder while investigating a case of stolen heroin from the evidence storage room from their police precinct.","Language":"English","Country":"United States","Awards":"4 nominations","Poster":"https://m.media-amazon.com/images/M/MV5BMGE1ZTQ0ZTEtZTEwZS00NWE0LTlmMDUtMTE1ZWJiZTYzZTQ2XkEyXkFqcGdeQXVyNTAyODkwOQ@@._V1_SX300.jpg","Ratings":[{"Source":"Internet Movie Database","Value":"6.9/10"},{"Source":"Rotten Tomatoes","Value":"42%"},{"Source":"Metacritic","Value":"41/100"}],"Metascore":"41","imdbRating":"6.9","imdbVotes":"246,119","imdbID":"tt0112442","Type":"movie","DVD":"12 Feb 2014","BoxOffice":"$65,807,024","Production":"Don Simpson/Jerry Bruckheimer Films","Website":"N/A","Response":"True"}

投稿ツールではmoviesの結果をさらにgrepしているのでキー毎に改行できれば行けそうですね。

といわけでコードはこちら

投稿のツールはpythonで作っているので取得ツールもpythonで作ります。

import requests
import sys
import json
import configure
import re

KEY = configure.APIKEY
url = 'http://www.omdbapi.com/'
gettitle = '+'.join(sys.argv[1:])
getinfo = ''.join([url, '?apikey=', KEY, '&t=', gettitle])

def main():

    movieinfo = requests.get(getinfo)
    dataload = json.loads(movieinfo.text)

    datadump = json.dumps(dataload, indent=0)
    shapedata = re.sub('"|,', "", datadump)

    print(shapedata)

if __name__ == '__main__':
    main()

よくあるrequestsを使った取得です。

クエリ用引数

映画タイトルを引数で渡しますが数単語あるのがほとんどなのでjoinを咬ませてstringにしています。

gettitle = '+'.join(sys.argv[1:])

APIキー無しのクエリはこんな感じです。

http://www.omdbapi.com/?t=bad+boys
jsonの成形

最終的に改行して出力したいのですが、dumpsのindent=0でできました。
でも一回loadsで辞書型にしないと改行されませんでした。

こんな感じに出力されます。
ここまで来たらほぼmoviesコマンドの結果と同じですね。

(movies) masashi@PC-ubuntu:~/movietweet$ python getinfo.py bad boys | head
{
Title: Bad Boys
Year: 1995
Rated: R
Released: 07 Apr 1995
Runtime: 119 min
Genre: Action Comedy Crime
Director: Michael Bay
Writer: George Gallo Michael Barrie Jim Mulholland
Actors: Will Smith Martin Lawrence Lisa Boyle

最後に投稿用のシェルスクリプトを修正して完成です。
これは上記の結果をgrepしているだけなので割愛します。

動かしてみる

実行してみましょう。

(movies) masashi@PC-ubuntu:~/movietweet$ bash twmovieinfo.sh bad boys
2021-07-24に「Bad Boys」を視聴しました。

Infomation
---
Year: 1995
Genre: Action Comedy Crime
Director: Michael Bay
Actors: Will Smith Martin Lawrence Lisa Boyle
Production: Don Simpson/Jerry Bruckheimer Films
---

投稿しますか?: [y/n]y
投稿を完了しました。

OK!
いいですね。

今までと同じ出力です。
ここだけ見たら中身が変わったなんてわからないですね。

まとめ

というわけで自作ツールでのAPI取得でした。
いままで使っていたツールが使えなくなったのは残念ですが仕方ないですね。

今回は自作なので突然エラーが起きても原因追求や修正はそんなに難しくないと思います。
あとはエラー判定等の処理を入れておかないとですね。

おまけ

本シリーズ

2020年上半期見た映画メモ & twitter取得ツール改修 - paloma blog

映画視聴ロガーを使って今年見た映画を振り返る - paloma blog

リポジトリ

github.com

2021年上半期見た映画メモ

今年も前半が終わりましたので映画を振り返ります。
ほとんどお出かけしていないので週2ペースでした。

取得ツール

映画視聴ロガーを使って今年見た映画を振り返る - paloma blog

(movies) masashi@PC-ubuntu:~/movietweet$ python gettw.py | grep 2021 | nl
     1  2021-06-27 21:53:23 Lara Croft: Tomb Raider
     2  2021-06-26 22:49:07 Lethal Weapon
     3  2021-06-20 22:53:52 Red Heat
     4  2021-06-19 21:56:03 Indiana Jones and the Kingdom of the Crystal Skull
     5  2021-06-13 22:06:43 The Medallion
     6  2021-06-12 22:07:21 Sorry to Bother You
     7  2021-06-06 21:49:56 Ex Machina
     8  2021-06-05 22:22:32 Knives Out
     9  2021-05-30 21:59:38 The Throwaways
    10  2021-05-29 23:23:15 Safe House
    11  2021-05-23 21:18:27 Fun with Dick and Jane
    12  2021-05-23 10:50:33 S.W.A.T.
    13  2021-05-16 20:49:01 The Great Gatsby
    14  2021-05-15 22:11:14 Eagle Eye
    15  2021-05-09 21:56:32 The Tuxedo
    16  2021-05-08 22:35:14 Contraband
    17  2021-05-05 21:56:10 Super 8
    18  2021-05-04 23:10:57 The Man from U.N.C.L.E.
    19  2021-05-04 09:30:55 Sleepless
    20  2021-04-25 22:03:32 Safe
    21  2021-04-25 10:05:08 Inside Man
    22  2021-04-18 22:45:24 The Other Guys
    23  2021-04-18 09:44:28 The Hummingbird Project
    24  2021-04-11 22:16:34 Daddy's Home
    25  2021-04-10 22:50:23 Collateral
    26  2021-04-04 21:59:44 Overdrive
    27  2021-04-03 22:55:33 Run All Night
    28  2021-03-20 22:25:17 The Commuter
    29  2021-03-13 22:08:20 Baby Driver
    30  2021-03-07 23:01:44 Limitless
    31  2021-03-06 21:51:25 Searching for Bobby Fischer
    32  2021-02-28 23:00:40 Cowboys &amp; Aliens
    33  2021-02-27 22:16:44 Steve Jobs
    34  2021-02-23 21:35:12 The Score
    35  2021-02-14 22:42:38 Batman Forever
    36  2021-02-13 22:53:35 Moneyball
    37  2021-02-06 23:33:08 The People vs. Larry Flynt
    38  2021-01-31 22:28:34 Julie &amp; Julia
    39  2021-01-30 21:59:41 Birds of Prey
    40  2021-01-24 21:38:01 30 Minutes or Less
    41  2021-01-17 21:46:38 The Last Runway
    42  2021-01-16 23:08:21 The Equalizer
    43  2021-01-11 22:03:38 Nerve
    44  2021-01-10 22:49:00 State of Play
    45  2021-01-10 12:40:13 Inception
    46  2021-01-04 22:34:46 Hustlers
    47  2021-01-04 10:10:38 The Accountant
    
    + 2021-02-07 22:42:00 Miss Bala (リメイクのためmoviesコマンドで拾えず)

で48本ですね。意外と見てるなあ。

上半期ベスト3

めちゃ悩みましたがベスト3です。

  1. Searching for Bobby Fischer (1993)
    邦題「ボビー・フィッシャーを探して」です。
    天才チェス少年が主人公です。
    序盤の快進撃や中盤の挫折を乗り越えて勝利に向かうのが王道ながらも面白かったです。
    精神面の成長というか。コーチとの確執まではいかないけどひと悶着あったりね。
    何より主人公が可愛いらしいですね。
  2. The Man from U.N.C.L.E. (2015)
    邦題「コードネーム UNCLE」です。
    CIAとKGBのスパイタッグでミッションを進めますが、人物、車、グッズと登場するものすべてがスタイリッシュでかっこいい映画でした。
    そっちばかり目が行っちゃってストーリーをあまり覚えてないのでもう一回見ます。
  3. The Commuter (2018)
    邦題「トレイン・ミッション」です。
    電車内である人物を見つけろと指示される話ですが、「次、どうなるの?」と思ってしまうストーリー展開が面白かったですね。電車内だけで話が進みますが密室サスペンスの感じがして良かったです。
    主演のリーアム・ニーソンがめちゃかっこいいです。

むすび

ベスト3を選ぶには数が多かったですね。
4半期毎にしようかなとも思いましたが半期くらいのほうが振り返るのが面白いのでこのペースでまとめていこうと思います。

「Julie & Julia」「The Hummingbird Project」「Inside Man」なんかもランクインさせたいほど面白かったです。
警察、ギャングものは相変わらず見ますが今回はCIAものも意外と多かった気がします。また、疲れたときはシンプルなアクション映画ということでジャッキーチェン作品も見るようになりましたね。
次回はSFなども攻めていきたいと思います。

毎回お酒飲みながらなので、あんまり覚えていないのもチラホラ…

後半もがんばりましょう。

easy-rsaで簡単に自宅CA構築+自己証明書発行

家の環境でWebサーバを作ってもhttpのまま使ってしまうんですが、これではイカンということでセキュリティの勉強も兼ねつつ自宅CAを作りたいと思います。

Let's Encryptでもいいかなと思ったのですが、家にサーバがある方が好き勝手できるので自宅CAを選択しました。

オレオレCA、証明書は昔に作ったことがあるんですが、opensslのコマンドを忘れてしまったのでまた調べなきゃと思っていたら簡単にできるパッケージを発見しました。

www.digitalocean.com

easy-rsaというパッケージですが、名前の通り簡単に証明書発行や管理ができるようです。
中身はopensslコマンドをいい感じに発行してくれるっぽいです。

今回は証明書が目的なのでアルゴリズム等は特にチューニング無しにします。

その前に環境のルール作り

CAサーバ作成に絡めて家のラボルールを決めます。

自宅ドメイン
  • szkmhome.lab

直IP運用でも問題ないのですが、Common name用にドメインを決めます。
ドメインを決めたからにはDNSサーバも作らないとですね。
ドメインは名前をもじりましたw

証明書期限ルール

作って終わりだと面白くないので、ある程度の期間で触るよう期限を切ります。

では構築していきましょう。


自宅CAサーバ作成

サーバ作っていきます。

インスタンス作成

家ではLXD環境を運用しているのでここにインスタンス作ります。

masashi@PC-ubuntu:~$ lxc version && lxc launch ubuntu: HomeCA
Client version: 4.15
Server version: 4.15
Creating HomeCA
Starting HomeCA
masashi@PC-ubuntu:~$ lxc exec HomeCA -- /bin/bash
root@HomeCA:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.2 LTS
Release:    20.04
Codename:   focal
パッケージインストール

aptで入れるだけ。
チュートリアルでは一般ユーザですが、コンテナなのでrootのまま進めます。

root@HomeCA:~# apt update
root@HomeCA:~# apt install easy-rsa

簡単です。

初期設定

チュートリアルに沿ってセッティングします。

コマンド類のシンボックリンク。

root@HomeCA:~# ln -s /usr/share/easy-rsa/* easy-rsa/ 
root@HomeCA:~# ls -l easy-rsa/
total 2
lrwxrwxrwx 1 root root 27 Jun 26 08:12 easyrsa -> /usr/share/easy-rsa/easyrsa
lrwxrwxrwx 1 root root 39 Jun 26 08:12 openssl-easyrsa.cnf -> /usr/share/easy-rsa/openssl-easyrsa.cnf
lrwxrwxrwx 1 root root 32 Jun 26 08:12 vars.example -> /usr/share/easy-rsa/vars.example
lrwxrwxrwx 1 root root 30 Jun 26 08:12 x509-types -> /usr/share/easy-rsa/x509-types

varsファイルを少しいじります。
コマンド用の変数ファイルっぽいですね。
個人的な部分はマスクしてます。

root@HomeCA:~/easy-rsa# cat vars
set_var EASYRSA_REQ_COUNTRY "JP"
set_var EASYRSA_REQ_PROVINCE    "XXXXX"
set_var EASYRSA_REQ_CITY    "XXXXX"
set_var EASYRSA_REQ_ORG     "Home labo CA"
set_var EASYRSA_REQ_EMAIL   "XXXXX"
set_var EASYRSA_REQ_OU      "Home labo"
set_var EASYRSA_CA_EXPIRE   3650
set_var EASYRSA_CERT_EXPIRE 365
set_var EASYRSA_DIGEST      "sha512"

CA証明書作成

ここからはeasyrsaコマンドベースです。

初期化。

root@HomeCA:~/easy-rsa# ./easyrsa init-pki

Note: using Easy-RSA configuration from: ./vars

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /root/easy-rsa/pki

CA作成。

root@HomeCA:~/easy-rsa# ./easyrsa build-ca nopass

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1f  31 Mar 2020
Generating RSA private key, 2048 bit long modulus (2 primes)
.............................................................+++++
.........................................................................................................................................................+++++
e is 65537 (0x010001)
Can't load /root/easy-rsa/pki/.rnd into RNG
139813523703104:error:2406F079:random number generator:RAND_load_file:Cannot open file:../crypto/rand/randfile.c:98:Filename=/root/easy-rsa/pki/.rnd
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:HomeCA.szkmhome.lab

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/root/easy-rsa/pki/ca.crt

これでCA証明書が作成されました。

CSR作成

CSRは証明書の申請者が作りますが、今回は同じコンテナ内で作ってしまいます。
ちなみに今回作成するのは同じくLXDで運用中のFirefly III用です。

秘密鍵
root@HomeCA:~/easy-rsa/csr# openssl genrsa -out server.key
Generating RSA private key, 2048 bit long modulus (2 primes)
.....................................+++++
...+++++
e is 65537 (0x010001)
CSR作成

subjectも一気に入れちゃいます。

root@HomeCA:~/easy-rsa/csr# openssl req -new -key server.key -out server.req -subj \
> /C=JP/ST=XXXXX/L=XXXXX/O=Home\ labo/CN=firefly.szkmhome.lab

root@HomeCA:~/easy-rsa/csr# ls
server.key  server.req

OK!

CAの署名

easy-rsaではCSRを一度専用ディレクトリに格納してから署名という流れのようです。

CSRインポート

CSRをインポートします。
最後のfireflyはたぶん次のコマンド用のCSRエイリアスですね。
これが無いとエラーになります。

root@HomeCA:~/easy-rsa# ./easyrsa import-req csr/server.req firefly

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1f  31 Mar 2020

The request has been successfully imported with a short name of: firefly
You may now use this name to perform signing operations on this request.
署名

インポートしたCSRを署名します。

証明書タイプをserverにします。
ここを変更すればclient証明書とかも作れるみたいです。

root@HomeCA:~/easy-rsa# ./easyrsa sign-req server firefly

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1f  31 Mar 2020


You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 365 days:

subject=
    countryName               = JP
    stateOrProvinceName       = XXXXX
    localityName              = XXXXX
    organizationName          = Home labo
    commonName                = firefly.szkmhome.lab


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
Using configuration from /root/easy-rsa/pki/safessl-easyrsa.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'JP'
stateOrProvinceName   :ASN.1 12:'XXXXX'
localityName          :ASN.1 12:'XXXXX'
organizationName      :ASN.1 12:'Home labo'
commonName            :ASN.1 12:'firefly.szkmhome.lab'
Certificate is to be certified until Jun 26 08:28:08 2022 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /root/easy-rsa/pki/issued/firefly.crt

完成!

中身を見てみましょう。

root@HomeCA:~/easy-rsa# openssl x509 -in pki/issued/firefly.crt -text | head -15
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            9f:e6:f3:e8:43:72:f4:92:a2:99:ec:90:a4:c1:14:eb
        Signature Algorithm: sha512WithRSAEncryption
        Issuer: CN = HomeCA.szkmhome.lab
        Validity
            Not Before: Jun 26 08:28:08 2021 GMT
            Not After : Jun 26 08:28:08 2022 GMT
        Subject: C = JP, ST = XXXXX, L = XXXXX, O = Home labo, CN = firefly.szkmhome.lab
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:

OKですね。
お手軽に証明書が作成できました!

まとめ

opensslはオプションが豊富にあって最初は非常にとっつきづらかったのですが、オレオレ証明書周りに必要なコマンドはなんとか触って覚えました。

しかし今回のeasy-rsaはコマンドがシンプルに整理されていてすぐに覚えることができました。
セキュリティのチューニングをするにはこのパッケージもopensslも、もっと勉強しないといけませんが、とりあえずお手軽にオレオレ証明書を作成することができました。

次回Webサーバに入れてみようと思います。

LXD環境のFirefly iiiのリカバリテストをする スクリプトで簡単にする編

前回行ったコンテナのリストアが思いの外簡単だったのでもっと簡単にします。
前回リカバリと言っていましたが、リストアのほうが適していそうなので今回はこちらで統一します。

ボタン一発でリストアできるのが理想ですね。

コンテナの命名規則

稼働中コンテナの名前は「firefly」ですがデプロイする際には重複しない様ちょっと変えたいです。

連番でもいいんですが通番をチェックしないといけないので面倒ですね。
一意にわかればいいのでランダムな文字列をくっ付けます。

ランダム文字列

shellでやろうとすると/dev/urandomから引っ張る例が多いですが、シンプルなの見つけました。

10 Ways to Generate a Random Password from the Linux Command Line

masashi@PC-ubuntu:~/scripts$ date | md5sum
f638d6896fb86b6e375a2d96a75ed06e  -

これで十分ですね。
あまり長いのも困るので8桁くらいまでにしましょう。

masashi@PC-ubuntu:~/scripts$ date | md5sum | fold -w 8 | head -n 1
cf94a96f

dockerのcontainer idみたいw

サーバ名とくっ付けます。
lxdはサーバ名はハイフンしか記号使えないみたいです。

masashi@PC-ubuntu:~/scripts$ echo firefly-$(date | md5sum | fold -w 8 | head -n 1)
firefly-aaa9676e
masashi@PC-ubuntu:~/scripts$ echo firefly-$(date | md5sum | fold -w 8 | head -n 1)
firefly-778bfd32
masashi@PC-ubuntu:~/scripts$ echo firefly-$(date | md5sum | fold -w 8 | head -n 1)
firefly-63d9eff8

いいんじゃないでしょうか。
間隔無しで打たない限りは重複しませんね。

スクリプト

コンテナのデプロイはlaunch打てばいいので簡単なんですが、重要なのはデータのインポートです。
前回はコンテナ内でsqlをインポートしましたが、今回ホストからデータを流し込みます。

テキストだからホストから直で行けるんじゃない?という考えのもとやってみます。

執筆中にいろいろテストしまして、コンテナを上げてすぐだとmysqldがあがっていなくてエラーになるのでステータスをウォッチするようにしました。
また、当初はpsで確認していましたがどこかエスケープしきれていないのかコマンドがミスるのでsystemdに直しました。

masashi@PC-ubuntu:~$ cmd="lxc exec firefly-a5d5d413 -- ps aux | grep mysqld"
masashi@PC-ubuntu:~$ $cmd
error: garbage option

Usage:
 ps [options]

 Try 'ps --help <simple|list|output|threads|misc|all>'
  or 'ps --help <s|l|o|t|m|a>'
 for additional help text.

For more details see ps(1).

最終的にスクリプトはこんな感じです。
mysqlのパスワードも平文なのでマスクします。
ここも暗号化しないとな。

masashi@PC-ubuntu:~/scripts$ cat firefly_restore.sh 
#!/bin/bash

uniqid=$(date | md5sum | fold -w 8 | head -n 1)

servername="firefly-$uniqid"

lxc launch firefly-image $servername

cmd="lxc exec $servername -- systemctl --no-pager status mysqld"

while :
  do
    $cmd
    if [ $? == 0 ] ; then
      break
    else
      sleep 1
      $cmd
    fi
  done

lxc exec $servername -- mysql --force -u fireflyiii -p<パスワード> -t fireflyiii < ./fireflyiii-db.sql

実行してみる

今回はscriptsフォルダで作業しています。

masashi@PC-ubuntu:~/scripts$ pwd
/home/masashi/scripts

dumpしたsqlも直下にあります。

masashi@PC-ubuntu:~/scripts$ ls fireflyiii-db.sql 
fireflyiii-db.sql

現状はこんな感じ。

masashi@PC-ubuntu:~/scripts$ lxc list
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
|      NAME      |  STATE  |        IPV4         |                     IPV6                      |   TYPE    | SNAPSHOTS |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| debian         | RUNNING | 10.28.57.205 (eth0) | fd42:24ab:b835:ae42:216:3eff:fe98:2560 (eth0) | CONTAINER | 0         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| dokuwiki       | RUNNING | 10.28.57.198 (eth0) | fd42:24ab:b835:ae42:216:3eff:fe2e:4f6a (eth0) | CONTAINER | 0         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| firefly        | RUNNING | 10.28.57.107 (eth0) | fd42:24ab:b835:ae42:216:3eff:fea8:7ef0 (eth0) | CONTAINER | 1         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| firefly-backup | STOPPED |                     |                                               | CONTAINER | 0         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| lxd-proxy      | RUNNING | 10.28.57.177 (eth0) | fd42:24ab:b835:ae42:216:3eff:fecd:d475 (eth0) | CONTAINER | 0         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+

ではスクリプト実行!

masashi@PC-ubuntu:~/scripts$ bash firefly_restore.sh 
Creating firefly-a5d5d413
Starting firefly-a5d5d413
● mariadb.service - MariaDB 10.3.25 database server
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
     Active: inactive (dead)
       Docs: man:mysqld(8)
             https://mariadb.com/kb/en/library/systemd/
● mariadb.service - MariaDB 10.3.25 database server
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
     Active: inactive (dead)
       Docs: man:mysqld(8)
             https://mariadb.com/kb/en/library/systemd/
● mariadb.service - MariaDB 10.3.25 database server
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
     Active: inactive (dead)
       Docs: man:mysqld(8)
             https://mariadb.com/kb/en/library/systemd/
● mariadb.service - MariaDB 10.3.25 database server
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
     Active: inactive (dead)
       Docs: man:mysqld(8)
             https://mariadb.com/kb/en/library/systemd/
● mariadb.service - MariaDB 10.3.25 database server
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
     Active: inactive (dead)
       Docs: man:mysqld(8)
             https://mariadb.com/kb/en/library/systemd/
● mariadb.service - MariaDB 10.3.25 database server
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
     Active: activating (start) since Tue 2021-06-22 23:13:23 JST; 1s ago
       Docs: man:mysqld(8)
             https://mariadb.com/kb/en/library/systemd/
    Process: 241 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)
    Process: 267 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
    Process: 273 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] && VAR= ||   VAR=`cd /usr/bin/..; /usr/bin/galera_recovery`; [ $? -eq 0 ]   && systemctl set-environment _WSREP_START_POSITION=$VAR || exit 1 (code=exited, status=0/SUCCESS)
   Main PID: 360 (mysqld)
      Tasks: 28 (limit: 14162)
     Memory: 78.5M
     CGroup: /system.slice/mariadb.service
             └─360 /usr/sbin/mysqld

Jun 22 23:13:23 firefly-a5d5d413 systemd[1]: Starting MariaDB 10.3.25 database server...
Jun 22 23:13:23 firefly-a5d5d413 mysqld[360]: 2021-06-22 23:13:23 0 [Note] /usr/sbin/mysqld (mysqld 1060 ...
Jun 22 23:13:23 firefly-a5d5d413 mysqld[360]: 2021-06-22 23:13:23 0 [Warning] Could not increase numbe…32186)
Hint: Some lines were ellipsized, use -l to show in full.
● mariadb.service - MariaDB 10.3.25 database server
     Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2021-06-22 23:13:24 JST; 475ms ago
       Docs: man:mysqld(8)
             https://mariadb.com/kb/en/library/systemd/
    Process: 241 ExecStartPre=/usr/bin/install -m 755 -o mysql -g root -d /var/run/mysqld (code=exited, status=0/SUCCESS)
    Process: 267 ExecStartPre=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
    Process: 273 ExecStartPre=/bin/sh -c [ ! -e /usr/bin/galera_recovery ] && VAR= ||   VAR=`cd /usr/bin/..; /usr/bin/galera_recovery`; [ $? -eq 0 ]   && systemctl set-environment _WSREP_START_POSITION=$VAR || exit 1 (code=exited, status=0/SUCCESS)
    Process: 466 ExecStartPost=/bin/sh -c systemctl unset-environment _WSREP_START_POSITION (code=exited, status=0/SUCCESS)
    Process: 468 ExecStartPost=/etc/mysql/debian-start (code=exited, status=0/SUCCESS)
   Main PID: 360 (mysqld)
     Status: "Taking your SQL requests now..."
      Tasks: 31 (limit: 14162)
     Memory: 84.3M
     CGroup: /system.slice/mariadb.service
             └─360 /usr/sbin/mysqld

Jun 22 23:13:23 firefly-a5d5d413 systemd[1]: Starting MariaDB 10.3.25 database server...
Jun 22 23:13:23 firefly-a5d5d413 mysqld[360]: 2021-06-22 23:13:23 0 [Note] /usr/sbin/mysqld (mysqld 1060 ...
Jun 22 23:13:23 firefly-a5d5d413 mysqld[360]: 2021-06-22 23:13:23 0 [Warning] Could not increase numbe…32186)
Jun 22 23:13:24 firefly-a5d5d413 systemd[1]: Started MariaDB 10.3.25 database server.
Jun 22 23:13:24 firefly-a5d5d413 /etc/mysql/debian-start[473]: Looking for 'mysql' as: /usr/bin/mysql
Jun 22 23:13:24 firefly-a5d5d413 /etc/mysql/debian-start[473]: Looking for 'mysqlcheck' as: /usr/bin/mys…heck
Jun 22 23:13:24 firefly-a5d5d413 /etc/mysql/debian-start[473]: This installation of MySQL is already upg…rade
Hint: Some lines were ellipsized, use -l to show in full.
ERROR 1062 (23000) at line 42: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 163: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 246: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 460: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 551: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 581: Duplicate entry '1' for key 'PRIMARY'

mysqldが上がるまで何回かウォッチしてますね。
ウォッチ部分の出力はいらないので後で直しましょう。
あと上がるまでちょっとかかるのでsleep 3秒くらいでいいかな。

また、最後の主キー重複エラーは前回と同じですね。
ということはデータを流し込めたということです。

コンテナは追加されています。

masashi@PC-ubuntu:~/scripts$ lxc list
+------------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
|       NAME       |  STATE  |        IPV4         |                     IPV6                      |   TYPE    | SNAPSHOTS |
+------------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| debian           | RUNNING | 10.28.57.205 (eth0) | fd42:24ab:b835:ae42:216:3eff:fe98:2560 (eth0) | CONTAINER | 0         |
+------------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| dokuwiki         | RUNNING | 10.28.57.198 (eth0) | fd42:24ab:b835:ae42:216:3eff:fe2e:4f6a (eth0) | CONTAINER | 0         |
+------------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| firefly          | RUNNING | 10.28.57.107 (eth0) | fd42:24ab:b835:ae42:216:3eff:fea8:7ef0 (eth0) | CONTAINER | 1         |
+------------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| firefly-a5d5d413 | RUNNING | 10.28.57.148 (eth0) | fd42:24ab:b835:ae42:216:3eff:fe66:8932 (eth0) | CONTAINER | 0         |
+------------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| firefly-backup   | STOPPED |                     |                                               | CONTAINER | 0         |
+------------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| lxd-proxy        | RUNNING | 10.28.57.177 (eth0) | fd42:24ab:b835:ae42:216:3eff:fecd:d475 (eth0) | CONTAINER | 0         |
+------------------+---------+---------------------+-----------------------------------------------+-----------+-----------+

アクセスしてみます

前回と同じ初期化画面ですね。

f:id:paloma69:20210623222152p:plain

前回とり忘れたログイン画面。

f:id:paloma69:20210623222205p:plain

メイン画面は前回と同じデータが入ってます。

f:id:paloma69:20210623222222p:plain

成功だー!

まとめ

スクリプトの出力と主キーエラーを綺麗にする必要がありますが、ボタン一発というかシェルスクリプト一撃でリストアできました。
監視のトリガーからスクリプト呼び出せば自動で復旧できるってことですよね。
外から突く用のproxy設定の問題はありますが、だいぶ現状に近い状態に戻せるようになりました。

launchまでの手順ならテスト環境のデプロイにも使えるし、今回のスクリプトは活用できそうです。

ちなみに他の人はリストア時は自作スクリプトじゃなくてなにかパッケージとか使ってるんですかね?
あまり事例が出てこなくてわからないのですが気になります。

lxdがあまり使われていないだけかな。

LXD環境のFirefly iiiのリカバリテストをする

LXDで運用しているFirefly iiiですが、前回コンテナのイメージ作成を行いました。
今回はイメージからのデプロイと実際のデータをリカバリできるかやってみます。

LXDコンテナのカスタムイメージを作成する - paloma blog

データベースバックアップ

王道にmysqldumpでやります。

ユーザは私しかいないですが一応テーブルロックしてdumpします。

定期的にやりたいのでスクリプトにしました。

masashi@PC-ubuntu:~/scripts$ cat fireflybkup.sh 
#!/bin/bash

path=/home/masashi/backup/firefly/

lxc exec firefly -- mysqldump --single-transaction -u fireflyiii -p<パスワード> -t fireflyiii > $path/fireflyiii-db.sql

実行します。

masashi@PC-ubuntu:~/scripts$ bash fireflybkup.sh 

バックアップディレクトリに作成されてます。

masashi@PC-ubuntu:~/scripts$ ls /home/masashi/backup/firefly/ -ltr
合計 340
drwxr-xr-x 9 masashi masashi   4096 1116  2019 nginx
-rw-r--r-- 1 masashi masashi    269 1120  2020 hosts
-rw-rw-r-- 1 masashi masashi 234853  620 15:18 fireflyiii-db.sql

イメージのデプロイ

前回作成のイメージからリカバリ用のインスタンスを作成します。

masashi@PC-ubuntu:~$ lxc image list
+---------------+--------------+--------+---------------------------------------------+--------------+-----------+----------+------------------------------+
|     ALIAS     | FINGERPRINT  | PUBLIC |                 DESCRIPTION                 | ARCHITECTURE |   TYPE    |   SIZE   |         UPLOAD DATE          |
+---------------+--------------+--------+---------------------------------------------+--------------+-----------+----------+------------------------------+
| firefly-image | 754669c7e39f | no     | Ubuntu 20.04 LTS server (20210201)          | x86_64       | CONTAINER | 873.23MB | May 8, 2021 at 2:32am (UTC)  |
+---------------+--------------+--------+---------------------------------------------+--------------+-----------+----------+------------------------------+
|               | 9ba1aa2f5dde | no     | ubuntu 20.04 LTS amd64 (release) (20210610) | x86_64       | CONTAINER | 360.92MB | Jun 12, 2021 at 5:36am (UTC) |
+---------------+--------------+--------+---------------------------------------------+--------------+-----------+----------+------------------------------+
masashi@PC-ubuntu:~$ lxc launch image:firefly-image recoverytest
Error: The remote "image" doesn't exist

イメージはローカルマシンにあるんですが、imageをつけるとリモートサーバを探してしまう様ですね。

masashi@PC-ubuntu:~$ lxc launch firefly-image recoverytest
Creating recoverytest
Starting recoverytest                      

これでOK。
リカバリインスタンスできてます。

masashi@PC-ubuntu:~$ lxc list  
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
|      NAME      |  STATE  |        IPV4         |                     IPV6                      |   TYPE    | SNAPSHOTS |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| debian         | RUNNING | 10.28.57.205 (eth0) | fd42:24ab:b835:ae42:216:3eff:fe98:2560 (eth0) | CONTAINER | 0         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| dokuwiki       | RUNNING | 10.28.57.198 (eth0) | fd42:24ab:b835:ae42:216:3eff:fe2e:4f6a (eth0) | CONTAINER | 0         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| firefly        | RUNNING | 10.28.57.107 (eth0) | fd42:24ab:b835:ae42:216:3eff:fea8:7ef0 (eth0) | CONTAINER | 1         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| firefly-backup | STOPPED |                     |                                               | CONTAINER | 0         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| lxd-proxy      | RUNNING | 10.28.57.177 (eth0) | fd42:24ab:b835:ae42:216:3eff:fecd:d475 (eth0) | CONTAINER | 0         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+
| recoverytest   | RUNNING | 10.28.57.247 (eth0) | fd42:24ab:b835:ae42:216:3eff:fe7f:7b52 (eth0) | CONTAINER | 0         |
+----------------+---------+---------------------+-----------------------------------------------+-----------+-----------+

リカバリsqlインポート

デプロイしたインスタンスはサービス起動済みなのでそのままリカバリsqlを流し込みます。

まずはインスタンスにファイルを配置。

masashi@PC-ubuntu:~$ lxc file push backup/firefly/fireflyiii-db.sql recoverytest/root/

ファイルも移動完了。

masashi@PC-ubuntu:~$ lxc exec recoverytest -- ls /root
fireflyiii-db.sql  snap

ここから先はコンテナに入ります。

masashi@PC-ubuntu:~$ lxc exec recoverytest -- /bin/bash

作成済みのデータベースがありますね。
中身はイメージ作成時に初期化済みです。

root@recoverytest:~# mysql -u fireflyiii -p -e 'show databases;'
Enter password: 
+--------------------+
| Database           |
+--------------------+
| fireflyiii         |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+

データをインポートしてみます。

root@recoverytest:~# mysql -u fireflyiii -p -t fireflyiii < /root/fireflyiii-db.sql 
Enter password: 
ERROR 1062 (23000) at line 42: Duplicate entry '1' for key 'PRIMARY'
root@recoverytest:~# 

主キーが重複で弾かれてしまいました…。
内容は後から確認するとして上書きしたらいける?

root@recoverytest:~# mysql --force -u fireflyiii -p -t fireflyiii < /root/fireflyiii-db.sql 
Enter password: 
ERROR 1062 (23000) at line 42: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 163: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 246: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 460: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 551: Duplicate entry '1' for key 'PRIMARY'
ERROR 1062 (23000) at line 581: Duplicate entry '1' for key 'PRIMARY'
root@recoverytest:~# 

引き続き重複エラーが出ていますが、コマンドは終了したのでアクセスしてみましょう。
エラーの件、データベースは本業ではないですが構造についてもっと勉強します。

アクセスしてみます

コンテナのホスト機からアクセスしてみます。

アクセスできましたが何かインストールかアップグレードをやってます。

f:id:paloma69:20210620182228p:plain

完了後いつものアカウントでログインしてみます。

OK。
本番のFireflyと同じ画面です。(資産は伏せさせていただきます)

f:id:paloma69:20210620182253p:plain

昨日支払ったゲーセンの内容も反映されています。

f:id:paloma69:20210620184107p:plain

リカバリ成功です!

まとめ

家の環境だと壊れてもいいかということで作って終わりのサーバが多いのですが、
Fireflyは気に入っていて壊れたら困るということで今回のリカバリテストを行いました。

DBの重複エラーは出ないのが理想ですが、とりあえずリカバリはできたのでいつ壊れてもOKですね。

コンテナ環境なのでシングルのホスト機が壊れたらおしまいなのですが、
イメージもエクスポートしてあるのでその際は他のLXD環境を作って凌ごうと思います。