工事現場備忘録

私の備忘録を私がどう書こうが私の自由であるとの信念に基づき自由に書いています

グローバルIP持ってないけど自宅サーバを外部公開したい in2024October

↓を今やるならでやりなおす.

koji-genba.hateblo.jp

変更点は主に下記2点

ってことでやっていこう.

目次(各項目リンク)

概要

出来上がるもののイメージが下記図.
GoogleCloudでVM立ててtailscale入れて自宅マシンとvpn接続する.
あとはGoogleCloudで通信受けてnginxでプロキシ.

構成図(雑)

主な作業の流れは以下.

自宅側

  1. ポート開けたり
  2. tailscaleセットアップ&接続

GoogleCloud側

  1. インスタンス作成
  2. ポート開け(GoogleCloud側ファイアウォール)
  3. (インスタンス初期セットアップ)
  4. tailscaleセットアップ&接続
  5. nginxでプロキシ構成

作業

tailscaleアカウント用意

もしtailscaleのアカウントを持っていないなら下記リンク右上[Get started]から適当なアカウントでログインし利用できるようにしておく.
tailscaleは外部アカウントでの認証しかやってないので,tailscaleのアカウント作成ってよりGoogleアカウント等々との紐づけって感じ.
tailscale.com

AdminConsole(下記画像のような感じの画面)まで到達できるようになればおk.

tailscale AdminConsole

自宅マシン側

tailscale.com 上記リンクから公開したいマシンのOSに合わせて作業し,接続までする.
Linuxであれば以下. tailscale upすると認証用のURLがコンソールに表示されるので,適当なブラウザ(別マシンからでもよい)で開いてログインし認証する.

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

windowsであればインストールしてタスクバーアイコンからあとは流れで.
tailscaleのAdminConsoleのMachinesに接続したマシンが表示されていれば接続完了.

Google Cloud側作業

GoogleCloudであることに理由はないので,AWSでもAzureでも他VPSでも好きな方法をとってもらって構わない.が今回はGoogleCloudで説明させてもらう.

1.インスタンス作成

安く済ませたいので無料枠を利用し,コスト0でインスタンスグローバルIPを用意する.

GoogleCloud Compute Engine (VM)の無料枠について

GoogleCloud Compute Engine (VM)の無料枠の条件はおおよそ下記.

  • us-west1, us-central1, us-east1のいずれかのリージョン
  • e2-micro インスタンス
  • 標準永続ディスク(上限30GB)
  • 通信下り1GB/月

これを満たすと1インスタンス/月は無料で使える(2024/10/26時点).IPアドレスに対する課金は無いとのこと.詳細は下記リンク先参照.
Google Cloud の無料プログラム  |  Google Cloud Free Program e2-microのスペックは下記リンク先
雑に言うと0.25vCPU, メモリ1GB.
Compute Engine の汎用マシン ファミリー  |  Compute Engine Documentation  |  Google Cloud

~GoogleCloud Compute Engine (VM)の無料枠について ここまで~

適当なGoogleアカウントでログインして以下へ
https://cloud.google.com/
ぽちぽちしてるとこの画面になると思うので画面上[プロジェクトの選択]→[新しいプロジェクト],参考画像に余計なプロジェクトシャットダウン中表示があるが気にしてはいけない.

GoogleCloud初期画面

プロジェクト名は適当でいい,場所も[組織なし]のままで問題なし.入力したら[作成].プロジェクト選択画面に戻ると思うので,作成したプロジェクトを選択.

プロジェクト作成画面

ここまで終われば画像のように[選択中のプロジェクト]に作成したプロジェクトが表示された状態のはず.そしたら[VMを作成]

プロジェクト選択された状態

おそらくこのようになるので[有効にする]して完了待ち.このあとどうなるのかちょっと忘れたけど,トップに戻れば間違いないので戻り,再度[VMを作成]へ.

ComputeEngineAPIを有効化するやつ

そしたらここからインスタンス作成作業.間違えるとお金がチャリンチャリンしちゃうので確実に確認しながら進めるように.
インスタント名は適当に好みでおk. リージョンは無料の中でも日本に近いus-west1(オレゴン)を選択.ゾーンはabcどこでもいい.他はノータッチ.

VMの基本設定画面

次にマシンの構成.E2-microを指定.

マシンの構成画面

次にOSとストレージ.[変更]から画像の画面へ.OSは特に指定ないが,DebianとかUbuntuとかRockyLinux(RHEL互換)のような無料で使えるものにすること.今回はUbuntu24.02LTSで進める.
ブートディスクの種類は標準永続ディスクを指定. サイズは30GB以下にすること.

OSとストレージ設定画面

次にネットワーキング.
[ネットワークインターフェース]の[default]を展開し,[外部IPアドレス]の項を選択.[静的外部IPアドレスを予約]を選択し,適当に名付けて作成.
他の項目はノータッチ.

ネットワーキング設定画面

ここまでやったら画面下の[作成]をクリック.インスタンスが生成されたらこのような画面になる.

VM作成後一覧画面

2.ポート開け(GoogleCloud側ファイアウォール)

公開したいサービスで利用するポートを開ける. まずGoogleCloudのファイアウォールに対して作業.先ほどのインスタンス一覧の画面から生成されたインスタンスを選択し,少々下へ.
[ネットワークインターフェース]のところの,[ネットワーク]の[default]を選択.(下記画像紫文字部分)

インスタンス詳細画面 ネットワーク部分

上タブを[ファイアウォール]に切り替え,[ファイアウォールルールを追加]を選択.

VPCネットワーク画面

あとは適当に設定して[作成]をクリック
多分設定項目はこれくらい?

  • 名前を適当に設定
  • トラフィックの方向 : 上り(内向き)
  • 一致した時のアクション : 許可
  • ソースフィルタ : IPv4 範囲
  • 送信元IPv4範囲 : 適当にいい感じに,特段事情なければ0.0.0.0/0(全て)
  • プロトコルとポート : 必要なものを指定

ファイアウォール設定

3.(インスタンス初期セットアップ)

インスタンス入ってアップデートとかsshのポート変えたりとかファイアウォール有効化して必要なポート開けるとかセキュリティ固めるとか各自好みで必要な作業諸々やってください.
インスタンス入るときは一覧画面にある[SSH]をポチるとブラウザ上でいい感じに接続してくれるのでおすすめ.22以外のポートでsshするときは横の矢印のとこからカスタムポート的なやつやればできる.
あと気になる人はGoogleCloud側ファイアウォールも固めておいてください.デフォだとssh-22とかrdp-3389とか開いてて物騒なので.

4. tailscaleセットアップ&接続

ローカル側マシンと同様.

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

tailscaleのAdminConsoleのMachinesに接続したインスタンスが表示されていれば接続完了.
この時点でローカル側マシンとクラウド上のインスタンスはtailscaleで接続されているはずだから,表示されているアドレスを使ってpingとか打って疎通を確認しておく.

5. nginxでプロキシ構成

通信を中継するためのnginxをセットアップする.

ビルド&インストール

aptとかdnfでインストールされるやつではモジュールだかなんだか足りないらしく動かんのでビルドするところから.
以下ではGoogleCloud上でビルドとかしてるけど,別にローカルでビルドして持って行ってもいい.そのほうが早いし環境きれいだし.

まず以下からnginxの一番新しいやつ確認.2024/10/26時点ではnginx-1.27.2なのでそのつもりで書く.違う場合は適宜読み替えて. nginx.org

そしたら下記のように前提等々インストールして,ビルド&インストール.
configureでエラー出たら都度いい感じに対応してください.

※debian系
sudo apt install clang libpcre3-dev zlib1g-dev make
※RHEL系
sudo dnf install clang pcre-devel zlib-devel make

wget http://nginx.org/download/nginx-1.27.2.tar.gz
tar zxvf nginx-1.27.2.tar.gz
cd nginx-1.27.2
./configure --with-stream --sbin-path=/usr/sbin/nginx --prefix=/etc/nginx
make && sudo make install

ついでにsystemctlで動かせるようにする.

sudo nano /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/conf/nginx.conf
ExecStart=/usr/sbin/nginx -c /etc/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target
コンフィグ記述

次にnginxのコンフィグ記述.

sudo rm /etc/nginx/conf/nginx.conf
sudo nano /etc/nginx/conf/nginx.conf

記述内容は,以下のような状態を想定すると,

  • ローカル側マシンtailscale上のアドレス : 100.99.100.100
  • 転送対象 : udp 19132

こうなる

worker_processes  1;

pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}
stream {
    upstream localServer {
        server 100.99.100.100:19132;
    }
    server {
        listen     19132 udp;
        proxy_pass localServer;
    }
}

以下のような状態を想定すると,

  • ローカル側マシンtailscale上のアドレス : 100.99.100.100
  • 転送対象 : tcp 25565

こうなる

worker_processes  1;

pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}
stream {
    upstream localServer {
        server 100.99.100.100:25565;
    }
    server {
        listen     25565;
        proxy_pass localServer;
    }
}

書いたら以下コマンドでエラー出ないかチェック.構文エラーあったら出るので修正.

sudo nginx -t

問題ない場合の出力.

nginx: the configuration file /etc/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/conf/nginx.conf test is successful
動かす

準備終わったので動かす

sudo systemctl daemon-reload
sudo systemctl enable --now nginx

sudo systemctl status nginxしてActive: active (running)になってれば問題なし.
あとはそれぞれ公開したいサービスがGoogleCloudで割り振られたグローバルIPで正常にアクセスできるか確認して問題なければ終了.グローバルIPは下記画像赤塗りつぶし部分に書いてある.

静的IPアドレスの記載場所

接続不良時確認項目

そんな面倒なことしてないしこれくらいじゃね

WSAでブルアカ動かしてぇな

動かせるけどクッソ重いしでもグラボは遊んでるしよく落ちるしで、いいところが画質良好だけ、やる意味ない。BlueStacksでいい。

1.andoridに普通にブルアカインストールしておく
2.なんとかしてapk取り出す
3.なんとかして/Andorid/obb/com.YostartJP.BlueArchiveを取り出す
4.adbとか使ってwsa内に押し込む
以上
あるいはwsa_pacman入れてどこぞからxapk拾ってきてインスコ

adb install .\bluearchive.apk
adb push .\com.YostarJP.BlueArchive\com.YostarJP.BlueArchive.obb /storage/emulated/0/Android/obb

Quest3を買った

Quest3を発売日に買ってしばらく使ったので感想

比較対象はRiftS、主な用途はDirtRally2.0とかAssettoCorsaとかそういうの

単体

画質
  • すごくすごい
  • 高解像度パネル+新光学系は当たり前だけど強い
  • コントラストはそれなり程度
    • HDRらしい。まあお値段考えりゃ妥当
  • 発色もそこまで変化なし
    総じてコントラストや発色はそこまですごく変わるってことは無いけど光学系とパネルのおかげで解像度マシマシでgood
画質以外
  • RiftS比だとやっぱり重い
    • 一週間もしたら慣れました
  • 標準ストラップだと1時間程度で痛いしつらい
    • 一週間たっても痛いもんは痛かったのでダメです
  • バッテリー持ちはそこまで良くはない、AirLinkで1時間ちょい程度?
  • 発熱は別に気にならない、触るとあったかいなー程度
  • コントローラーからリングが消えたのは結構楽
    • 物理的に小さいため取り回しが少し楽
    • 手からはみ出る部分が小さいため、コントローラーだけ何かにぶつけて破壊する心配が少し減った
  • コントローラーのストラップ交換しにくいのはちょっと減点
  • パススルー画質がすごい
    • かぶったまま迷うことなくトイレに行ける
    • この記事を書くこともできる
    • 大学内を徘徊することもできる
    • 手の周辺が歪む?
      • 手の周辺に何らかの映像補正がかかっている(立体感のやつか?)
      • 手を動かすと周辺が水面の如く揺れる
      • 本体正面カメラのうち下側をテープとかでふさぐと映像の立体感が消える代わりに歪は無くなる

ケーブルはこれ

https://www.amazon.co.jp/gp/product/B08FVM2WTJ/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&th=1

PCスぺは以下
Ryzen9 5900X
DDR4-3200 64GB (32*2)
RX6800XT (Adrenaline23.9.1)

ネット環境
1Gbps有線
PC---------ix2215
       |
       |1Gbps有線
       |
Quest3-----RT-AC68U(APモード)
11ac 866Mbps
直線5m以内障害物無し

Debug Tool無し 80Hz5408x2896
  • なんかいかにもエンコードした動画です感がある
  • RiftSのほうが画質いいんじゃね…?
  • 遅延は感じられない
    DebugTool有 H.264/750Mbps 80Hz5408x2896
  • これは綺麗
  • 純粋にRiftSから解像度上がってGoodになったような絵
  • 遅延も気にならん
  • すごくGoodです
DebugTool無し、Dynamic200Mbps
  • うーん……
    • (当然と言えば当然だけど)RiftS以下画質
  • んでもまあ無線ってのを考えれば……まぁ……
  • 遅延は意外と気にならないレベル
    DebugTool有 H.264/500Mbps
  • やるやん!
  • 有線750Mbpsとそこまで画質変わらんかもな
    • 有線500Mbpsと変わらん(当然)
  • 遅延も特に気にならない
    • DirtRally2.0やっていつもと同じタイムで走れました
  • バッテリーはモリモリ減る。1.5時間ぐらいだっけ(忘れた)

BOBOVR M3Pro

BOBOVRのM3Proヘッドストラップも買った

感想
  • 完璧で究極の装着感
  • RiftSよりすごくいい
    • やっぱ重量バランスなんでしょうか
  • バッテリー持ちも格段に良くなった
    • バッテリー残量を理由にプレイ中断することは無くなった
    • 足りないならバッテリー買い足して随時交換すればいいし
  • 純正がM3Proを採用するべきでは?

まとめ

ARもMRも知らん!ゲームにしか使ってねぇ!でも後悔もしてねぇ!満足!買ってよかった!
これまでありがとうRiftS!お前は予備機行き!

やっとcurve optimizerした

ずっとPPT/TDC/EDC指定だけで5900Xを使っていたけどいい加減にcurve optimizer(以下co)を使った話

自動調整

RyzenMasterはどうやらcoのセッティングを自動で導いてくれるらしい。なんと素晴らしいのだろう
と思いさっそく実行したところ全コア-30が適用された

えぇ……でもまぁあんたほどの人がそう言うんなら……
ということで全コア-30で使ってみると確かに多少ベンチのスコアは伸びたし"ベンチ中は"意外と落ちなかった
んじゃ大丈夫かぁと思っていたところブラウジングとかそういうそこまでじゃない負荷がかかるときにまあ落ちまくる落ちまくる

手動調整

仕方ないので自分でセッティングすることにした
どうやら優秀なコアはあまり落とさず他のコアはガッツリ落とすのが常道らしいので優先コアは-5、他は-30にしてみた
やっぱり落ちた、ので他は-25に
やっぱり落ちた、ので他は-20に
たまに落ちるな、ので他は-15に
落ちなくなった!!

結論

ってことで優先コア-5、他-15でとりあえず運用
本当はそれぞれのコアごとに落ちない見極めをした方がベストなんだろうけどそこまでやる気は無い、やらないよりはマシぐらいのラインで十分
ってかそこまで詰めても得られるリターンが小さくて小さくて……

apcupsd+apcupsd-cgiをpodman(docker)で動かす

タイトル通り、podman環境下でapcupsdとapcupsd-cgiを動かす話です。
こんなことしなくてもdockerhubになんぼでも先駆者の叡智がうpされてんだからそれ使えばいいじゃんとは思うけどやりたかったんだ。

環境

RocyLinux8.8で動くKVMで動くRocyLinux8.8(KVM上)のPodman

# cat /etc/rocky-release
Rocky Linux release 8.8 (Green Obsidian)

# podman version
Client:       Podman Engine
Version:      4.4.1
API Version:  4.4.1
Go Version:   go1.19.4
Built:        Wed May 17 06:22:45 2023
OS/Arch:      linux/amd64

UPSはCyberPowerのCPJ1200
CPJ1200 - UPSシステム | CyberPower
安くてそこそこの容量で結構な出力。

前提

UPSはUSB接続、これをコンテナ内で動くapcupsdに繋いでやる。ついでにapcupsd-cgiでブラウザからも状態が見られるようにする。 今回はVM上でコンテナを動かすんでホストのUSBをVMに渡してやる。
なんかCP1500って言われてるけど間違いなくCPJ1200です。まあAPCUPS互換であればAPCだろうがOMRONだろうがCyberPowerだろうがなんでもヨシ!

やるよ

Dockerfile書くよ

Dockerfile書く。docker-composeとか知らん。

FROM rockylinux:8

RUN dnf update -y && \
    dnf install epel-release -y && \
    dnf install apcupsd apcupsd-cgi apcupsd-gui httpd -y

COPY ./etc_apcupsd.conf /etc/apcupsd/apcupsd.conf
COPY ./httpd_apcupsd.conf /etc/httpd/conf.d/apcupsd.conf

COPY ./startup.sh /startup.sh
RUN chmod 744 /startup.sh

CMD ["/startup.sh"]

適当にこんな感じ。epel追加してやってapcupsdその他必要な奴をインスコするだけ。apcupsd-guiはいらない気もするけど。
COPYはコンフィグ渡すためのやつです。あとはapcupsdとhttpd両方を起動したいからCMDで起動用のスクリプトを呼ぶ。

んでその起動用のスクリプト

#!/bin/bash

/usr/sbin/httpd
/bin/rm -f /etc/apcupsd/powerfail
/sbin/apcupsd -b

httpdは普通に起こすだけ。FOREGROUNDとかしたくなるけどしなくてよかった。下2行はapcupsd起動するやつ、よくわからんのでdnfしたときにsystemdに登録されるやつを頂いてきた。

需要無い気もするけどコンフィグの中身も一応

/etc/apcupsd/apcupsd.conf どういう設定かちゃんと覚えてはいないけど、ぼちぼちバッテリーきつくなってきたらシャットダウンされるように組んではいたはず。

## apcupsd.conf v1.1 ##
# 
#  for apcupsd release 3.14.14 (31 May 2016) - redhat
#
# "apcupsd" POSIX config file

#
# Note that the apcupsd daemon must be restarted in order for changes to
# this configuration file to become active.
#

#
# ========= General configuration parameters ============
#

# UPSNAME xxx
#   Use this to give your UPS a name in log files and such. This
#   is particulary useful if you have multiple UPSes. This does not
#   set the EEPROM. It should be 8 characters or less.
UPSNAME CPJ1200

# UPSCABLE <cable>
#   Defines the type of cable connecting the UPS to your computer.
#
#   Possible generic choices for <cable> are:
#     simple, smart, ether, usb
#
#   Or a specific cable model number may be used:
#     940-0119A, 940-0127A, 940-0128A, 940-0020B,
#     940-0020C, 940-0023A, 940-0024B, 940-0024C,
#     940-1524C, 940-0024G, 940-0095A, 940-0095B,
#     940-0095C, 940-0625A, M-04-02-2000
#
UPSCABLE usb

# To get apcupsd to work, in addition to defining the cable
# above, you must also define a UPSTYPE, which corresponds to
# the type of UPS you have (see the Description for more details).
# You must also specify a DEVICE, sometimes referred to as a port.
# For USB UPSes, please leave the DEVICE directive blank. For
# other UPS types, you must specify an appropriate port or address.
#
# UPSTYPE   DEVICE           Description
# apcsmart  /dev/tty**       Newer serial character device, appropriate for 
#                            SmartUPS models using a serial cable (not USB).
#
# usb       <BLANK>          Most new UPSes are USB. A blank DEVICE
#                            setting enables autodetection, which is
#                            the best choice for most installations.
#
# net       hostname:port    Network link to a master apcupsd through apcupsd's 
#                            Network Information Server. This is used if the
#                            UPS powering your computer is connected to a 
#                            different computer for monitoring.
#
# snmp      hostname:port:vendor:community
#                            SNMP network link to an SNMP-enabled UPS device.
#                            Hostname is the ip address or hostname of the UPS 
#                            on the network. Vendor can be can be "APC" or 
#                            "APC_NOTRAP". "APC_NOTRAP" will disable SNMP trap 
#                            catching; you usually want "APC". Port is usually 
#                            161. Community is usually "private".
#
# netsnmp   hostname:port:vendor:community
#                            OBSOLETE
#                            Same as SNMP above but requires use of the 
#                            net-snmp library. Unless you have a specific need
#                            for this old driver, you should use 'snmp' instead.
#
# dumb      /dev/tty**       Old serial character device for use with 
#                            simple-signaling UPSes.
#
# pcnet     ipaddr:username:passphrase:port
#                            PowerChute Network Shutdown protocol which can be 
#                            used as an alternative to SNMP with the AP9617 
#                            family of smart slot cards. ipaddr is the IP 
#                            address of the UPS management card. username and 
#                            passphrase are the credentials for which the card 
#                            has been configured. port is the port number on 
#                            which to listen for messages from the UPS, normally 
#                            3052. If this parameter is empty or missing, the 
#                            default of 3052 will be used.
#
# modbus    /dev/tty**       Serial device for use with newest SmartUPS models
#                            supporting the MODBUS protocol.
# modbus    <BLANK>          Leave the DEVICE setting blank for MODBUS over USB
#                            or set to the serial number of the UPS to ensure 
#                            that apcupsd binds to that particular unit
#                            (helpful if you have more than one USB UPS).
#
UPSTYPE usb
DEVICE 

# POLLTIME <int>
#   Interval (in seconds) at which apcupsd polls the UPS for status. This
#   setting applies both to directly-attached UPSes (UPSTYPE apcsmart, usb, 
#   dumb) and networked UPSes (UPSTYPE net, snmp). Lowering this setting
#   will improve apcupsd's responsiveness to certain events at the cost of
#   higher CPU utilization. The default of 60 is appropriate for most
#   situations.
#POLLTIME 60

# LOCKFILE <path to lockfile>
#   Path for device lock file. This is the directory into which the lock file
#   will be written. The directory must already exist; apcupsd will not create
#   it. The actual name of the lock file is computed from DEVICE.
#   Not used on Win32.
LOCKFILE /var/lock

# SCRIPTDIR <path to script directory>
#   Directory in which apccontrol and event scripts are located.
SCRIPTDIR /etc/apcupsd

# PWRFAILDIR <path to powerfail directory>
#   Directory in which to write the powerfail flag file. This file
#   is created when apcupsd initiates a system shutdown and is
#   checked in the OS halt scripts to determine if a killpower
#   (turning off UPS output power) is required.
PWRFAILDIR /etc/apcupsd

# NOLOGINDIR <path to nologin directory>
#   Directory in which to write the nologin file. The existence
#   of this flag file tells the OS to disallow new logins.
NOLOGINDIR /etc


#
# ======== Configuration parameters used during power failures ==========
#

# The ONBATTERYDELAY is the time in seconds from when a power failure
#   is detected until we react to it with an onbattery event.
#
#   This means that, apccontrol will be called with the powerout argument
#   immediately when a power failure is detected.  However, the
#   onbattery argument is passed to apccontrol only after the 
#   ONBATTERYDELAY time.  If you don't want to be annoyed by short
#   powerfailures, make sure that apccontrol powerout does nothing
#   i.e. comment out the wall.
ONBATTERYDELAY 6

# 
# Note: BATTERYLEVEL, MINUTES, and TIMEOUT work in conjunction, so
# the first that occurs will cause the initation of a shutdown.
#

# If during a power failure, the remaining battery percentage
# (as reported by the UPS) is below or equal to BATTERYLEVEL, 
# apcupsd will initiate a system shutdown.
BATTERYLEVEL 50

# If during a power failure, the remaining runtime in minutes 
# (as calculated internally by the UPS) is below or equal to MINUTES,
# apcupsd, will initiate a system shutdown.
MINUTES 5

# If during a power failure, the UPS has run on batteries for TIMEOUT
# many seconds or longer, apcupsd will initiate a system shutdown.
# A value of 0 disables this timer.
#
#  Note, if you have a Smart UPS, you will most likely want to disable
#    this timer by setting it to zero. That way, you UPS will continue
#    on batteries until either the % charge remaing drops to or below BATTERYLEVEL,
#    or the remaining battery runtime drops to or below MINUTES.  Of course,
#    if you are testing, setting this to 60 causes a quick system shutdown
#    if you pull the power plug.   
#  If you have an older dumb UPS, you will want to set this to less than
#    the time you know you can run on batteries.
TIMEOUT 300

#  Time in seconds between annoying users to signoff prior to
#  system shutdown. 0 disables.
ANNOY 300

# Initial delay after power failure before warning users to get
# off the system.
ANNOYDELAY 60

# The condition which determines when users are prevented from
# logging in during a power failure.
# NOLOGON <string> [ disable | timeout | percent | minutes | always ]
NOLOGON disable

# If KILLDELAY is non-zero, apcupsd will continue running after a
# shutdown has been requested, and after the specified time in
# seconds attempt to kill the power. This is for use on systems
# where apcupsd cannot regain control after a shutdown.
# KILLDELAY <seconds>  0 disables
KILLDELAY 0

#
# ==== Configuration statements for Network Information Server ====
#

# NETSERVER [ on | off ] on enables, off disables the network
#  information server. If netstatus is on, a network information
#  server process will be started for serving the STATUS and
#  EVENT data over the network (used by CGI programs).
NETSERVER on

# NISIP <dotted notation ip address>
#  IP address on which NIS server will listen for incoming connections.
#  This is useful if your server is multi-homed (has more than one
#  network interface and IP address). Default value is 0.0.0.0 which
#  means any incoming request will be serviced. Alternatively, you can
#  configure this setting to any specific IP address of your server and 
#  NIS will listen for connections only on that interface. Use the
#  loopback address (127.0.0.1) to accept connections only from the
#  local machine.
NISIP 0.0.0.0

# NISPORT <port> default is 3551 as registered with the IANA
#  port to use for sending STATUS and EVENTS data over the network.
#  It is not used unless NETSERVER is on. If you change this port,
#  you will need to change the corresponding value in the cgi directory
#  and rebuild the cgi programs.
NISPORT 3551

# If you want the last few EVENTS to be available over the network
# by the network information server, you must define an EVENTSFILE.
EVENTSFILE /var/log/apcupsd.events

# EVENTSFILEMAX <kilobytes>
#  By default, the size of the EVENTSFILE will be not be allowed to exceed
#  10 kilobytes.  When the file grows beyond this limit, older EVENTS will
#  be removed from the beginning of the file (first in first out).  The
#  parameter EVENTSFILEMAX can be set to a different kilobyte value, or set
#  to zero to allow the EVENTSFILE to grow without limit.
EVENTSFILEMAX 10

#
# ========== Configuration statements used if sharing =============
#            a UPS with more than one machine

#
# Remaining items are for ShareUPS (APC expansion card) ONLY
#

# UPSCLASS [ standalone | shareslave | sharemaster ]
#   Normally standalone unless you share an UPS using an APC ShareUPS
#   card.
UPSCLASS standalone

# UPSMODE [ disable | share ]
#   Normally disable unless you share an UPS using an APC ShareUPS card.
UPSMODE disable

#
# ===== Configuration statements to control apcupsd system logging ========
#

# Time interval in seconds between writing the STATUS file; 0 disables
STATTIME 0

# Location of STATUS file (written to only if STATTIME is non-zero)
STATFILE /var/log/apcupsd.status

# LOGSTATS [ on | off ] on enables, off disables
# Note! This generates a lot of output, so if         
#       you turn this on, be sure that the
#       file defined in syslog.conf for LOG_NOTICE is a named pipe.
#  You probably do not want this on.
LOGSTATS off

# Time interval in seconds between writing the DATA records to
#   the log file. 0 disables.
DATATIME 0

# FACILITY defines the logging facility (class) for logging to syslog. 
#          If not specified, it defaults to "daemon". This is useful 
#          if you want to separate the data logged by apcupsd from other
#          programs.
#FACILITY DAEMON

#
# ========== Configuration statements used in updating the UPS EPROM =========
#

#
# These statements are used only by apctest when choosing "Set EEPROM with conf
# file values" from the EEPROM menu. THESE STATEMENTS HAVE NO EFFECT ON APCUPSD.
#

# UPS name, max 8 characters 
#UPSNAME UPS_IDEN

# Battery date - 8 characters
#BATTDATE mm/dd/yy

# Sensitivity to line voltage quality (H cause faster transfer to batteries)  
# SENSITIVITY H M L        (default = H)
#SENSITIVITY H

# UPS delay after power return (seconds)
# WAKEUP 000 060 180 300   (default = 0)
#WAKEUP 60

# UPS Grace period after request to power off (seconds)
# SLEEP 020 180 300 600    (default = 20)
#SLEEP 180

# Low line voltage causing transfer to batteries
# The permitted values depend on your model as defined by last letter 
#  of FIRMWARE or APCMODEL. Some representative values are:
#    D 106 103 100 097
#    M 177 172 168 182
#    A 092 090 088 086
#    I 208 204 200 196     (default = 0 => not valid)
#LOTRANSFER  208

# High line voltage causing transfer to batteries
# The permitted values depend on your model as defined by last letter 
#  of FIRMWARE or APCMODEL. Some representative values are:
#    D 127 130 133 136
#    M 229 234 239 224
#    A 108 110 112 114
#    I 253 257 261 265     (default = 0 => not valid)
#HITRANSFER 253

# Battery charge needed to restore power
# RETURNCHARGE 00 15 50 90 (default = 15)
#RETURNCHARGE 15

# Alarm delay 
# 0 = zero delay after pwr fail, T = power fail + 30 sec, L = low battery, N = never
# BEEPSTATE 0 T L N        (default = 0)
#BEEPSTATE T

# Low battery warning delay in minutes
# LOWBATT 02 05 07 10      (default = 02)
#LOWBATT 2

# UPS Output voltage when running on batteries
# The permitted values depend on your model as defined by last letter 
#  of FIRMWARE or APCMODEL. Some representative values are:
#    D 115
#    M 208
#    A 100
#    I 230 240 220 225     (default = 0 => not valid)
#OUTPUTVOLTS 230

# Self test interval in hours 336=2 weeks, 168=1 week, ON=at power on
# SELFTEST 336 168 ON OFF  (default = 336)
#SELFTEST 336

/etc/httpd/conf.d/apcupsd.conf 標準のやつについて192.168.1.0/24から見えるようにしただけだったような

#
# apcupsd configuration file for Apache Web server
#

# files are off the documentroot of Web server
Alias /apcupsd /var/www/apcupsd
<Directory /var/www/apcupsd>
 AddHandler cgi-script cgi pl
 Options ExecCGI
</Directory>

#
# Allow only local access at default
# Change the ".example.com" to match your domain or modify
# access rights to your needs to enable remote access also.
#
<Directory "/var/www/apcupsd">
    DirectoryIndex upsstats.cgi
    AllowOverride None
    Options ExecCGI Indexes
  <IfModule mod_authz_core.c>
    # Apache 2.4
    Require ip 192.168.
  </IfModule>
  <IfModule !mod_authz_core.c>
    # Apache 2.2
    Order deny,allow
    Deny from all
    Allow from 192.168.
    Allow from ::1
  </IfModule>
</Directory>

UPSのデバイスファイルはいずこぞ

私の場合は/dev/usb/hiddev0でした。
~完~

他の人の環境だとどうなるかなんて私にはわかりません。 外国人ニキgithub見てたらそこ読んでたからここかな~ぐらいでやったら当たっただけ。
私はルートでpodman動かしちゃってるから関係なかったけどルートレスで動かすならudevルール書いて権限どうにかしないとダメなはず。

なんとなくこうだった気がして書いたけど全部嘘だった部分

ここに書いてある作業しても(少なくとも私の環境では)なんの意味もありませんでした。

次にコンテナにデバイスファイル渡しやすくするためにちょっとudevルール作る
まずlsusbしてVendorIDとProductIDを調べる

# lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 005: ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS
Bus 001 Device 002: ID 0627:0001 Adomax Technology Co., Ltd 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

my環境ではこうなった。CP1500がUPSなんでVendorIDとProductIDはそれぞれ0764、0501。
そしたらudevルールの作成。/etc/udev/rules.dディレクトリにこういう内容、ファイル名は適当に。私は見たサイトに合わせて99-serial.rulesにした。

SUBSYSTEM=="usb", ATTRS{idVendor}=="0764", ATTRS{idProduct}=="0501", SYMLINK+="cp1500", MODE="0666"

usb接続の0764 0501についてcp1500ってリンクを作りますってことらしい。そしたら再起動するか下コマンドでルールを反映させる。

udevadm control --reload

すると/dev/cp1500ってファイルが生成されてるはず。されてればおk。

ですが生成されたファイルをpodman runに渡してもUPS認識しません、ってことをここまで書いてから思い出した。

コンテナ作って動かす

あとは普通にビルドして動かすだけ

podman build -t apcupsd:latest .
podman run -d --name apcupsd --device=/dev/usb/hiddev0:/dev/usb/hiddev0 -p 80:80 -p 3551:3551 apcupsd:latest

ビルドは普通にビルドするだけ。
runの指定は
コンテナ名:apcupsd
ホストの/dev/usb/hiddev0をコンテナに/dev/usb/hiddev0で渡す
ホストのポート80と3551をそれぞれコンテナの80と3551に対応させる
イメージはapcupsdのlatest
ってやつ。
ちゃんと動いてたらこれで動いてるはず。あとは他PCのapcupsdをいろいろやってこいつ参照させてシャットダウンできるようにしましょ(割愛)。
cgiはhttp://[ipアドレスorホスト名]/apcupsd/multimon.cgiで見られるはず。

コンテナからホストの電源断するやつは今度やる。絶対やる。

作業中見たサイト群

GitHub - gregewing/apcupsd: Dockerize apcupsd, but keep the ability to power off the docker host in event of a power failure.
最初からこれ使えばよかったような気がすごくします。

APCUPSDの設定方法
config書くたびに確認してる。

podmanコンテナ内からUSBメモリ内ファイルへアクセスする方法 | Armadilloサイト
読んだけどそこまで関係なかった。

Podmanコンテナでpcsc_toolsを動かす
ルートレスでpodmanやるなら多分関係ある。

USBカメラをDockerから使いたい - Qiita
dockerでの話だけどコマンドは基本似たようなもんだし。

Armadillo-IoT(G3/G3L)/X1/640:USBデバイスのデバイスファイルに別名を付ける | Armadilloサイト
UPSのデバイスファイルどこやねん!?って時に使えるかなと思ったけど使えなかった。

宅内向けにunbound使ってDoTで外部に問い合わせる良さげなDNSサーバを用意する

仮想マシンも増えてきて毎回IP手打ちは面倒くさいためbindで内部向けDNSサーバを立てていたけれどもunboundを使うともっといい感じになれると聞いた.
せっかくunboundへの移行をするのだからついでに外部にはDoT(DNS over TLS)を使って問い合わせるようにしてみたのでメモ.

環境

# cat /etc/redhat-release
Rocky Linux release 8.7 (Green Obsidian)

とりあえずインスコ

dnf update ca-certificates
dnf install unbound 
dnf info unbound --installed
インストール済みパッケージ
名前         : unbound
バージョン   : 1.16.2
リリース     : 2.el8
Arch         : x86_64
サイズ       : 5.9 M
ソース       : unbound-1.16.2-2.el8.src.rpm
リポジトリー : @System
repo から    : appstream
概要         : Validating, recursive, and caching DNS(SEC) resolver
URL          : https://www.unbound.net/
ライセンス   : BSD
説明         : Unbound is a validating, recursive, and caching DNS(SEC) resolver.
             :
             : The C implementation of Unbound is developed and maintained by NLnet
             : Labs. It is based on ideas and algorithms taken from a java prototype
             : developed by Verisign labs, Nominet, Kirei and ep.net.
             :
             : Unbound is designed as a set of modular components, so that also
             : DNSSEC (secure DNS) validation and stub-resolvers (that do not run
             : as a server, but are linked into an application) are easily possible.

ルート証明書更新するためにdnf update ca-certificatesをやっておく.unboundは2023/02/13に普通にdnfすると1.16.2を拾ってきた.別にこれで問題ないためこれで進める.(1.12以降でDoT・DoHに対応)

conf書く

/etc/unbound以下にunbound.confなんていかにもって感じのconfファイルがある.でもその中でconf.d以下の*.confをincludeするためそっちに書いたほうがいい.
なおconf.d以下は何もせずとも標準のunbound.confのままでincludeされる.そしてincludeするたびにincludeされるため自分でincludeを追加で書いたりすると設定が重複してエラーになる.

fatal error: interface: 0.0.0.0 present twice, cannot bind same ports twice.

とかはそれで出る.私はこれで2時間ほどハマった.ただのバカでは?
せっかくだし内容ごとに分離しておいて扱いやすいようにしておく.

main.conf
server:
    # 外部からアクセスできるように0.0.0.0を指定
    interface: 0.0.0.0
    #ipv4のみ
    do-ip4: yes
    do-ip6: no
    #tcpもudpも使う
    do-udp: yes
    do-tcp: yes

    # ローカルからの問い合わせを許可
    access-control: 0.0.0.0/0 refuse
    access-control: 127.0.0.0/8 allow
    access-control: 192.168.1.0/24 allow

    # バージョンを知られないようにする?
    hide-version: yes
    hide-identity: yes

    # roothintを指定する
    #sudo curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache
    root-hints: "/etc/unbound/root.hints"

    # ログファイルにログを出す
    logfile: "/var/log/unbound.log"
    use-syslog: no
    log-time-ascii: yes

メインのconfはこの程度で動くはず.
仮にこれを使うのであれば実行前にsudo curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cacheを実行してroot-hintsを用意する必要がある.あとcron.montlyとか使って定期的に更新するように.

ドメイン名.conf
server:
    local-zone: "kojigenba-srv.com." transparent

    # 末尾のドット忘れ注意
    local-data: "router.kojigenba-srv.com.      IN  A   192.168.1.1"

    # 逆引き
    local-data-ptr: "192.168.1.1    router.kojigenba-srv.com"

IP手打ちから逃れるためって意味ではメインのやつ.末尾のドット忘れに注意(2敗)

dns-over-tls.conf
server:
    tls-cert-bundle: "/etc/ssl/certs/ca-bundle.crt"
    tls-system-cert: yes

forward-zone:
    name: "."
    forward-tls-upstream: yes

    forward-addr: 1.1.1.1@853 # Cloudflare DoT
    forward-addr: 1.0.0.1@853 # Cloudflare DoT

    forward-addr: 8.8.8.8@853 # Google DoT
    forward-addr: 8.8.4.4@853 # Google DoT

    forward-addr: 103.2.57.5@853 # IIJ DoT
    forward-addr: 103.2.57.6@853 # IIJ DoT

forward-tls-upstream:yesにしておけばDoT使ってくれるっぽい.@以下はポート番号.DoHも同じように443で書けば使えるっぽい雰囲気を醸し出している.
IIJのを書いているけどIIJ Public DNSは2024/3/31までの提供のため注意.でもDoTとかDoHとかでの問い合わせにしか返してくれないらしいからテスト用にはちょうどいい.

大したリクエスト数ないだろうからパフォーマンスチューニングはサボりました.

動かす

conf一通り書いたら

# unbound-checkconf
unbound-checkconf: no errors in /etc/unbound/unbound.conf

ってなることを確認.ならなかったら頑張って修正.
もしfatal error: server-key-file: "/etc/unbound/unbound_server.key" does not existみたいに~~.keyが無いって感じのエラーであれば

systemctl start unbound-keygen

で解決するかもしれない.unbound-keygenはunboundを起動すると勝手に起動するから途中で起動していれば出ない.
あとは普通に

systemctl enable unbound
systemctl start unbound

とかして動かす. ドメイン名.confに書いたとおりに接続できるか一応確認する.
DNSSECも標準で有効になってるはず.dig . SOA +dnssecでadフラグ立ってればおk.

# dig +dnssec whitehouse.gov

; <<>> DiG 9.11.36-RedHat-9.11.36-5.el8_7.2 <<>> +dnssec whitehouse.gov
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50176
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;whitehouse.gov.                        IN      A

;; ANSWER SECTION:
whitehouse.gov.         30      IN      A       192.0.66.168
whitehouse.gov.         30      IN      RRSIG   A 13 2 300 20230216100158 20230213090158 35095 whitehouse.gov. 09Zpl6ScSrwOwZ5vgC29UWWIMBFhHoIuc+z+I2SZE9UOqkoJyNFf/YBv MNWUbQdmudHXqSHPR0QZCacuLmDaRA==

;; Query time: 0 msec
;; SERVER: 192.168.1.4#53(192.168.1.4)
;; WHEN: 火  2月 14 00:08:46 JST 2023
;; MSG SIZE  rcvd: 169

flags: qr rd ra ad;でadが含まれているしRRSIGで署名も得られた.

# dig +dnssec dnssec-failed.org

; <<>> DiG 9.11.36-RedHat-9.11.36-5.el8_7.2 <<>> +dnssec dnssec-failed.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 18710
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;dnssec-failed.org.             IN      A

;; Query time: 0 msec
;; SERVER: 192.168.1.4#53(192.168.1.4)
;; WHEN: 火  2月 14 00:10:14 JST 2023
;; MSG SIZE  rcvd: 46

flagsにadがないしstatusがSERVFAILになっている.検証失敗はこうなる.
検証成功したり失敗したりしてるってことはDNSSECが仕事してるってことだろう,たぶん.

外への問い合わせについては前述のようにIIJ Public DNSはDoTとかDoHでの問い合わせにしか返してくれないらしいからここで確認しとけば大丈夫(かもしれない)
暗号化されてるか不安であれば

tcpdump -i enp1s0 port 853 and src host 192.168.1.4 -w test.pcap -v

とかしてパケットキャプチャしてwiresharkに突っ込んで中身を覗けばいい.ProtocolがDNSではなくTCPとかTLSとかになっていて内容が分からないようになっているはず.

その他どうでもいいこと

DoTとDoHだと何となくDoTはシステムとかが使ってDoHはブラウザとかが使う印象があったから今回はDoTで設定した.firefoxなんかはcloudflareのDoHを使う設定が存在してワンクリックでセットアップできてしまうけど自宅鯖にホスト名でアクセスできなくなるからダメだなぁになってしまう. 本来は途中で盗み見されるのこわいぴえん🥺であればISP提供のDNSを使っておけばいい.だからDoTとかDoHが必要なのはpublicDNSを使うとき.私はアパート付属回線で実態は光ファイバ一本を複数部屋で共有してるやつだしISP調べてもDNS鯖アドレス分からないし提供されてるのかもわからないし自動設定にするとアパート内で回線分割する装置に問い合わせしてて結局どこに問い合わせてるのかよく分からないしで悲しくなったからDoHとかDoTで遊ぶことにした.ただDoHとかDoTとかはpublicDNS側から見ると通常のDNSよりも多くの情報が手に入るはずだから一概にプライバシーが向上するとは言えない.そのへんはpublicDNS側の情報収集ポリシーを信じるしかないっぽい.私は気にしないことで解決しました.気にしないならDoTも必要ないのでは?