NixOS & Home Managerのセットアップメモ

NixOS 23.11をセットアップした時のメモ。 目標 NixOS環境については以前構築したことがあるが、勉強のためもう一度一から構築する 今後、NixOSの環境をすぐに構築できるような設定ファイル、リポジトリを作る なるべくNix Flakesを使う NixOSの設定ファイルはNix言語で記述するが、自由度が結構高くて、どうファイル分け、ディレクトリ分けをしていくのかが悩ましい。 今回はWikiの紹介されていたdotfilesリポジトリを参考にしようと思う。 とはいえ、まだまだNixOSの初学者のため、小さな部分を少し真似して作っていく。 インストールディスクの起動 Download Nixのページ下部にある「NixOS the Linux distributeion」からISOイメージをダウンロードしてくる。 ダウンロードリンクとして、Graphical ISO ImageとMinimal ISO Imageがあるが、今回は後者でやる。 Graphical ISO Imageも一度試したが、ウィザード形式で設定をポチポチ進めるだけで設定が出来上がるので分かりやすい。おそらく初学者はこれで作成された configuration.nix を眺めて、少しずつ設定を理解していくのがよいのだと思う。 Minimal ISO Imageはコンソールでインストール作業を行う。パーティションを分けたり、ファイルシステムを作ったりするのは自分でやることになる。今回は勉強のためにこれでやる。 作業の大枠はNixOS 23.11 manualに乗っているのでそれに従う。 自分の環境の場合は、ESXiの入ったPCがあるので、コンテンツライブラリにそれをアップロードし、仮想マシン作成の時にそれをCDデバイスとしてセットする 物理HWに入れる場合、ISOイメージをUSBやCDに焼いておき、起動する 起動すると次の画面になるので、一番上を選択してEnterする。 SSH接続できるようにする しばらくすると以下の画面になる。 文章を読むと、 To log in over ssh you must set a password for ether “nixos” or “root” with passwd (prefix with sudo for “root”), or … と親切にもSSHへの入り方のガイドが示されている。証跡を残すためには画像よりもテキストの方が取りやすいため、SSHで作業することにする。なお、このままコンソール上で作業する場合、loadkeys でキーボードのレイアウトを変えないと記号が思った通りに打てないので注意。 ガイド通り、パスワードを変える。 SSHで入るためには、もちろんSSHで接続しに行く側との疎通ができないといけない。これは環境によって様々。 有線の場合 DHCP有効の場合:すでにIPアドレスが取得できている状態だと思う。ip a で確認可能 journalctl -xe を見るとわかるが、どうやら dhcpcd が動いている模様 DHCP無効の場合:ip a addなりifconfigなりでIPアドレスを手動設定する 無線の場合:wpa_supplicantを使った方法で接続できるっぽいので、これを試せばよいと思う 自分の環境の場合は、VM作成時にNICをつけたし、ルータのDHCPも有効なのですでにIPアドレスが取得できている状態だった。なのでそのままログインできる。 ...

2024-02-11 · (updated 2024-04-20) · 12 min · 2536 words

ブログをGitHub Actionsを使ったビルドに切り替えたときの手順

このブログはまだCI/CDも分からない頃に始めたのもあって、GitHub Actionsを使っていないビルドをしていた。いちいちビルドしてリポジトリにpushするのも面倒だし、Chanomic Sketchを昨年開設したときにGitHub Actionによるビルドを学んだので、重い腰を上げて切り替えようと思った。そのときのメモ。 色々調べていたら、Chanomic Sketchで上げたときとは違って、gh-pagesのようなブランチを作らなくても良い方法が作られていたので、その方法でやっていく。 基本的な手順はHugoの公式に書かれているが、一応現時点でのやり方をメモっておく。 (参考)現状のデプロイ方法と今後のデプロイ方法の比較 現状は、 hugo new posts/.../index.mdで記事を作成 記事を書いてhugo serverで確認 書き終わったらindex.mdのdraft: tureを外してcommit hugoコマンドを単体で実行してページのビルドをする → docs/下にHTMLが展開されるので、それをcommit pushする と手順を踏んでいたが、今回の変更によって、 hugo new posts/.../index.mdで記事を作成 記事を書いてhugo serverで確認 書き終わったらindex.mdのdraft: tureを外してcommit pushする と手順が1個減る。また、docs/ディレクトリがなくなるためコミットログがすっきりすることも期待される。 ブログの修正 まず、config.tomlのpublishDirにてdocs/下にHTMLを展開するようにしてあったが、この記述はいらないので消す。 1 publishDir="docs" また、docs/ディレクトリは git rm -rfで消す。 GitHub Pagesの設定 Pagesの設定に移動して、Build and deploymentの項目のSourceを、「Deploy from a branch」から「GitHub Actions」に変更。 workflowの記述 次に、.github/workflows/<適当な名前>.yaml を作成し、そこに以下の記述をする。 注)これは現時点でのHugoの公式をそのまま借りてきている。最新版は公式を参照すること。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 name: Deploy Hugo site to Pages on: push: branches: - master workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: false defaults: run: shell: bash jobs: build: runs-on: ubuntu-latest env: HUGO_VERSION: 0.121.0 steps: - name: Install Hugo CLI run: | wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \ && sudo dpkg -i ${{ runner.temp }}/hugo.deb - name: Install Dart Sass run: sudo snap install dart-sass - name: Checkout uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - name: Setup Pages id: pages uses: actions/configure-pages@v4 - name: Install Node.js dependencies run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" - name: Build with Hugo env: HUGO_ENVIRONMENT: production HUGO_ENV: production run: | hugo \ --gc \ --minify \ --baseURL "${{ steps.pages.outputs.base_url }}/" - name: Upload artifact uses: actions/upload-pages-artifact@v2 with: path: ./public deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v3 やっている内容としては、 ...

2024-01-14 · (updated 2024-01-14) · 2 min · 297 words

NixOSをWSL2上で構築したときのメモ

年末からお正月の間帰省したときにWindowsのラップトップを持っていった。しかしWSL2にはUbuntuしか入っておらず、最近デスクトップで使っているNixOSが入っていなかった。そこで試しに構築してみたときのメモ。最低限コーディングができる環境が整った。 (IT系あるあるだけれど)NixOS-WSLの開発はまあまあ早いため、ここに書いてある内容もすぐ陳腐化してしまいそう。 インストール RepositoryのReleasesからnixos-wsl.tar.gzをDLしてくる コマンドプロンプト or PowerShell で以下のコマンドを実行 1 2 3 wsl --import NixOS .\NixOS\ nixos-wsl.tar.gz --version 2 wsl -d NixOS nix-channel --update Flake化による初回セットアップ 今回はなるべくnix-channelを使わず、flake.nixからなるべく必要なファイルを入れるようにしたい。そのほうが、今後再セットアップするときにそのflakeファイルを指定するだけで環境が構築できることを期待しているため。 とはいえ、現状のNixOSにはVimもGitも入っておらず限界があるので、それはChannelから入手する。まず現時点での最新版のnixosのChannelを登録する。 1 2 sudo nix-channel --add https://nixos.org/channels/nixos-23.11 nixos sudo nix-channel --update 次にVimとGitを入れる。Vimはテキスト編集のため、Gitはnix-flakeの動作のために必要。 1 nix-shell -p vim git NixOSで最強のLinuxデスクトップを作ろうやUsing nix flakes with NixOSに書かれている内容を参考に進めていく。 まずホームディレクトリに移動し、適当なディレクトリnixos-configを作り、そこにNixOSの設定ファイル(configuration.nix)を持ってくる。 1 2 3 4 cd ~ mkdir nixos-config cd nixos-config cp /etc/nixos/* . flake.nixを作成し以下のようにする。 inputsにnixosのリポジトリと、NixOS-WSLのリポジトリを指定する inputsの書き方はattribute setとurl-likeな書き方の2種類がある。url-likeな書き方だとtag指定の方法がわからなかったので、NixOS-WSLのinputに関してはattribute setで書いている nixosSystemの引数としてspecialArgsが指定でき、これでconfiguration.nixに引数を渡せる 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { inputs = { nixos.url = "github:NixOS/nixpkgs/nixos-23.11"; nixos-wsl = { type = "github"; owner = "nix-community"; repo = "NixOS-WSL"; ref = "2311.5.3"; }; }; outputs = inputs: { nixosConfigurations = { wsl = inputs.nixos.lib.nixosSystem { system = "x86_64-linux"; modules = [ ./configuration.nix ]; specialArgs = { nixos-wsl = inputs.nixos-wsl; }; }; }; }; } 現在、configuration.nixではWSL用のモジュールをnixos-wsl Channelから取得するようになっている。 ...

2024-01-13 · (updated 2024-01-14) · 3 min · 610 words

FastAPIとOAuth2でユーザログイン機能(備忘録)

何をするか 以下の3つの機能を実装する。 ユーザを作成する。 ユーザを認証してトークンを生成し返す。 ユーザがログインしていないと401を返す:ここでは「ユーザ情報を返すAPI」を作成。 ユーザがログインしているかどうかで異なるレスポンスを返す:ここでは「ログインしているかどうかを真偽値で返すAPI」を作成。 方針 使う技術・フレームワーク、ライブラリなど PythonとMySQLはDocker Composeで動かす。 PythonのパッケージはPoetryで管理する。 APIサーバーはFastAPI + uvicornで動かす。 認可の方式としてOAuth2.0を用いる。認可グラントのタイプはシンプルなROPC。 なぜこれを選んだのかというと、単純にFastAPIのドキュメントに書かれていたのがこれだったため。いつかほかのタイプも実装してみたい。 DBのマイグレーションはalbemicを使用してみる。今回はユーザ情報しか作らないので、alembicの使用は間違いなくオーバーなのだが、勉強のため使ってみる。 プロジェクト構成 プロジェクトディレクトリは次のようにする。 DBに関するCRUDs処理はcrudsモジュールに書く。 DBと対応するモデルはmodelモジュールに書く。 APIのリクエストボディ、レスポンスボディの形式はschemas.pyに書く。 DBのセッションの作成はdb.pyに書く。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 . ├── api │ ├── cruds │ │ ├── __init__.py │ │ └── user.py │ ├── models │ │ ├── __init__.py │ │ └── user.py │ ├── routers │ │ ├── __init__.py │ │ └── auth.py │ ├── schemas │ │ ├── __init__.py │ │ └── user.py │ ├── db.py │ ├── main.py │ └── migrate_db.py ├── Dockerfile ├── docker-compose.yaml ├── poetry.lock └── pyproject.toml ちなみにこの図はtree -I __pycache__ --dirsfirsで生成。 ...

2023-06-29 · (updated 2023-06-30) · 7 min · 1388 words

Alembicを使ったDBマイグレーション(備忘録)

経緯 Alembicというライブラリを知ったので、試しに触ってみたメモ。 そもそもAlembicとは Alembicとは、DBマイグレーションライブラリの1つ。SQLAlchemyと一緒に用いる。 今回やってみること 今回行うマイグレーションは、以下の3つ。 空 User(email, password)を作成 User(email, password, name)に変更 使い方 Alembicの初期化 使うDBとの紐づけ エンティティ作成 マイグレーションファイルを作成 マイグレーション 想定する状況と準備 FastAPI上でWeb APIを提供し、その中でDBを操作することを想定する。ただし、メインテーマがマイグレーションのため、この記事でFastAPIの話は一切出ない。プロジェクト作成について、詳しくはFastAPI入門を参照するとよい。この記事では、ディレクトリ構成を大きく参考にしている。 パッケージ管理にはpoetryを使う。 DBにはMySQLを使う。 マイグレーションは同期処理で行うため、入れるのはPyMySQLだけでよい。しかしFastAPIでDBを処理するときに非同期での操作を行うことを見越し、aiomysqlを入れる。この時点でPyMySQLも入る。 1 poetry add sqlalchemy alembic aiomysql alembicの初期化 次のコマンドを実行する。 1 poetry run alembic init alembic プロジェクト配下にalembic/というディレクトリが生成される。 使うDBとの紐づけ alembic.iniを編集する。sqlalchemy.urlの記述を見つけたら以下のようにする。 1 sqlalchemy.url = mysql+pymysql://<url>/<name>?charset=utf8 <url>と<name>にはそれぞれ、mysqlのサーバーのURLとそのDBの名前を指定する。例えばmysqlがdbというDocker Composeのサービスとして稼働しており、3306ポートで受け付けており、そのDBの名前がappdbだった場合、次のようになる。 1 sqlalchemy.url = mysql+pymysql://root@db:3306/appdb?charset=utf8 api/db.pyにDBエンティティのベースを作っておく。 1 2 3 from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() alembic/env.pyのtarget_metadataを以下のようにする。 1 2 3 from api.db import Base target_metadata = Base.metadata 空のマイグレーション まだエンティティを作成していない状態でマイグレーションを行ってみる。 マイグレーション用のファイル作成 以下でマイグレーション用のファイルを作成する ...

2023-06-20 · (updated 2023-06-25) · 3 min · 588 words

ReactとD3.jsを使ったWordCloudの作成(備忘録)

注意 筆者はReact歴1週間なので、筋の良い書き方でなかったり、間違った書き方であったりするかもしれない。 前半は車輪の再発明をしてしまっている。書いている途中にreact-d3-cloudライブラリの存在に気づいたので、記事の最後にサンプルコードを記載している。 プロジェクト準備 このあたりは人によりけりだが、ここでは次のようにする。 Reactのビルド環境はDockerないしDocker Composeで構築。 Reactのプロジェクトはcreate-react-appで構築。 それではまずDocker・Docker Composeの構築から。 プロジェクトディレクトリを適当に作成し、そこにdocker-compose.yamlを書く。 1 2 3 4 5 6 7 8 9 10 version: "3.0" services: app: image: node:20-slim volumes: - ./app:/src ports: - 3000:3000 command: npm start working_dir: /src 続いて次のコマンドを実行してcreate-react-appを導入し、実行する。 1 $ docker-compose run --rm app sh -c "npm install -g create-react-app && create-react-app ." これによりappディレクトリが作成され、中にReactのプロジェクトが生成される。 ...

2023-06-11 · (updated 2023-06-11) · 4 min · 777 words

ニューラルネットワーク ノート - 誤差逆伝播の計算

誤差逆伝播法の数式の説明なんて世の中にたくさんあると思うが、理解のために自分でもまとめる。 特に添字などのミスがあると思うので、見つけ次第修正する。 誤差逆伝播の計算 (1) 問題設定 入力を第 $0$ 層、出力を第 $L$ 層とする。ニューラルネットワークはよく次のようなグラフで描かれる。 円がノードを表す。ノードに入っていく矢印が入力、出ていく矢印が出力を表す。 第 $l$ 層 $j$ 番目のノードの出力を $y_j^l$ とおく (注意: この記事では $y_j^{l}$ の $l$ は添字を表すものとする。累乗ではない。これから現れる変数についても同様)。これはある関数 $f_l$ を用いて以下の式で表される。$f_l$ は活性化関数と呼ばれる。 ただし、$u_j^{l}$ は前の層の出力を用いて計算される線形和で、以下のように定義される。 このような、線形和を取って $f$ を適用するという流れは次のようなグラフで描かれる。 この $\sum | f$ のノードがたくさん集まって第 $l$ 層を形成している。 損失関数 $E$ は、重み$w_{ij}^{l}$ についての関数である。これは出力値 $y_i^{L}$ と教師データ $\tilde{y}_i$ との違いを測る尺度であるから、$y_i^{L}$ の関数でもある。 例えば、以下の二乗誤差は損失関数の一種である。 定義中に $w_{ij}^{l}$ が含まれていないじゃないか、と思うかもしれないが、$y_i^{L}$ の定義中に $w_{ij}^{L}$ が含まれている。さらにその中の $y_i^{L-1}$ 中に $w_{ij}^{L-1}$ が含まれている。以下同様にして $w_{ij}^l$ は $E$ の中に含まれている。 ...

2022-01-15 · (updated 2022-11-24) · 3 min · 516 words

PureScriptでパーサーコンビネータを触る (2) テキストファイル

前回の記事 と合わせて1つの記事にする予定だったが、前回があまりに長くなってしまったので分割した。 ある書式に従ったテキストファイルをパースすることを考える。パースしたデータを整形し、HTML文書として出力するところまでやる。 前回インポートした関数で今回使うものは、(漏れが無ければ)以下の通り。 1 2 3 4 import Control.Alt ((<|>)) import Control.Lazy (defer) import Text.Parsing.Parser (Parser, fail) import Text.Parsing.Parser.String (char) テキストの仕様 テキストファイルは、複数のentryで構成される。 1つのentryはタイトルtitleと中身bodyで構成される。 titleは[と]でくくられる。 titleとbodyの間、bodyと次のentryのtitleの間には、1つの改行と、0個以上の空行があり得る。それらはbodyには含まない。 空行とは、0個以上のスペースだけから構成される行のことである。 BNF風に書くと次のようになるだろう。 1 2 3 4 5 6 <entries> = (0個以上の<entry>) <entry> = <title> "\n" <empty lines> <body> "\n" <empty lines> <title> = "[" (文字列) "]" <body> = (先頭、末尾が<empty lines>でないような文字列) <empty lines> = (0個以上の<empty line>) <empty line> = (0個以上のスペース) "\n" 例えば、以下のファイルがあったとする。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [Title1] line1 line2 line3 line4 [Title2] line1 line2 [Title3] line1 line2 line3 これは次のようにパースされる。 ...

2021-12-31 · (updated 2021-12-31) · 9 min · 1750 words

PureScriptでパーサーコンビネータを触る (1) 四則演算のパース

PureScriptのパーサーコンビネータにpurescript-parsingがある。これはHaskellのParsecが基になっているので、使い方はParsecとほとんど同じだと思われる(とはいえ、Parsecを使ったことはあまりない)。これを用いて四則演算のパーサーを実装してみたが、うまく動かず詰まる点がいくつかあった。その備忘録。 パーサーコンビネータの準備 % spago install parsing 後々使うので以下のパッケージもインストール。 % spago install either integers maybe strings arrays lists src/Main.pursに以下の記述を追加。 1 2 3 4 import Text.Parsing.Parser (Parser) parser :: Parser String String parser = pure "Hello" REPLを起動して、動くか確認する。どんな文字列を食わせても"Hello"としか結果を返さないパーサーの完成。 > import Main > import Text.Parsing.Parser (runParser) > runParser "hoge" parser (Right "Hello") REPLでMain.pursをリロードする場合は:rをREPLで実行する。 数字のパース 1文字取得 1文字の数字を読み取りたいなら、Text.Parsing.Parser.Tokenにdigitがあるのでそれを使う。 1 2 3 4 5 import Text.Parsing.Parser.Token (digit) parser :: Parser String Char parser = digit > runParser "12345" parser (Right '1') 1文字以上取得 1文字以上を取得したいなら、Data.Array.Someを使う。 1 2 3 4 5 import Data.Array as Array parser :: Parser String (Array Char) parser = Array.some digit > runParser "12345" parser (Right ['1','2','3','4','5']) 0文字以上の場合はData.Array.manyを使えば良い。 ただし、この関数は実装で(:)を使っている。この計算量は O(配列の長さ) のため(参考)、 もし効率を重視したいのであればData.List.manyもしくはData.List.someを使えば良い。 ...

2021-12-30 · (updated 2021-12-30) · 11 min · 2146 words

モンテカルロ法による積分

今年の7月くらいに書き始め、存在をすっかり忘れていた記事をUP。 モンテカルロ法でどうやって積分計算をするのか、重点サンプリングとはどのようなものなのかついて勉強したので、そのメモ。 一般論 $$ \begin{aligned} \int_{\Omega_0} f(x) dx &= \int_{\Omega_0} \frac{f(x)}{p(x)}p(x)dx\\ &= \mathbb{E}\left[\frac{f(x)}{p(x)}\right] \end{aligned} $$ ここで、$p$ は確率密度関数。上の $\mathbb{E}$ が期待値であるためには、 $$ \int_{\Omega_0} p(x) dx = 1 $$ である必要がある。 大数の法則より、確率分布 $p$ に従う 標本 $x_n\ (n = 1, 2, \ldots, N)$ に対して、$N$ が十分大きければ、 $$ \mathbb{E}\left[\frac{f(x)}{p(x)}\right] \simeq \frac{1}{N} \sum_{n=1}^{N} \frac{f(x_n)}{p(x_n)} $$ となるから、結局、 $$ \begin{aligned} \int_{\Omega} f(x) dx \simeq \frac{1}{N} \sum_{n=1}^{N} \frac{f(x_n)}{p(x_n)} \end{aligned} $$ と近似できる。 ちなみに、$p(x_n) = 0$ なる $x_n$ が選ばれることは絶対に無い(確率0だから)。よって分母が0になることを心配する必要はない。 定義域を広げる $p$ の定義域をもう少し広げられる。$\Omega \supset \Omega_0$ であれば、集合$A$に関する指示関数を $\bm{1}_A$ と書くことにして、 ...

2021-12-28 · (updated 2021-12-28) · 2 min · 409 words