nix flake
inputs = {...}
: input の set
input は { url : string }
hoge = {fuga = ??? }
のようなデータは unexpected flake input attribute fuga
になる
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs";
}
は
inputs.nixpkgs = {
type = "github";
owner = "NixOS";
repo = "nixpkgs";
}
に対応している. ある種の alias か?
interpreter が下のような処理をしているのかしら.
for (input <- inputs) {
input <- parse(input.url) <+> (input.type,input.owner,input.repo).mapN(Input)
// do something
}
self: super :
パターンは reduce
, foldLeft
みたいなメンタルモデルで考える. self
は最終結果、super
は途中の値. reduce
のように final: prev:
のように書いているケースもある.
fonts.fonts = with pkgs; [
recursive
(nerdfonts.override { fonts = [ "JetBrainsMono" ]; })
];
を見るとパッケージの何かの値を override
関数で書き換えられそう.
home.packages = [
(pkgs.coursier.override {version = "..."; })
]
を試してみたら、
error: anonymous function at /nix/store/...source/pkgs/development/tools/coursier/default.nix:1:1 called with unexpected argument 'version'
at /nix/store/jp3rbrvh2gb9n9c37rrrhzm8xfn0mkbc-source/lib/customisation.nix:69:16:
68| let
69| result = f origArgs;
| ^
70|
(use '--show-trace' to show detailed location information)
coursier の設定を見ると以下のようになっている. pkgs.coursier は関数か.
override
では lib, stdenv, fetchurl, makeWrapper, jre, writeScript, common-updater-scripts, coreutils, git, gnused, nix, nixfmt
しか上書きできない...?
{ lib, stdenv, fetchurl, makeWrapper, jre, writeScript, common-updater-scripts
, coreutils, git, gnused, nix, nixfmt }:
let
version = "2.1.0-M7";
zshCompletion = fetchurl {
url =
"https://raw.githubusercontent.com/coursier/coursier/v${version}/modules/cli/src/main/resources/completions/zsh";
sha256 = "0afxzrk9w1qinfsz55jjrxydw0fcv6p722g1q955dl7f6xbab1jh";
};
nerdfont の default.nix
は以下のようになっている. coursier も引数に version
を追加したらバージョンを override
で切り替えられる...?
{ stdenv
, fetchurl
, lib
, unzip
# To select only certain fonts, put a list of strings to `fonts`: every key in
# ./shas.nix is an optional font
, fonts ? []
# Whether to enable Windows font variants, their internal font name is limited
# to 31 characters
, enableWindowsFonts ? false
}:
let
# both of these files are generated via ./update.sh
version = import ./version.nix;
よく出てくる stdenv と lib の型がわからん.
こういうことらしい. なるほど?
package の override はここにまとまっていた. https://nixos.org/guides/nix-pills/nixpkgs-overriding-packages.html
nix derivation のデバッグ
nix repl
で :l <nixpkgs>
をするといろいろなパッケージが import? される.
関数は __functionArgs プロパティをチェックすると必要な引数がわかる.
nix derivation を使って scala native のコードをコンパイルする例
@main def run = println("Hello!")
{ pkgs ? import <nixpkgs>{} }:
pkgs.stdenv.mkDerivation {
pname = "mypkg";
version = "0.1.0";
buildInputs = [
pkgs.scala-cli
pkgs.jdk17
pkgs.which
pkgs.openssl
];
src = ./src;
buildPhase = ''
export HOME="$(mktemp -d)"
echo $HOME
scala-cli --power -Duser.home=$HOME package --server=false main.scala --native -o main -f
'';
installPhase = ''
mkdir -p $out/bin
install main $out/bin/main
'';
}
nix-build drv.nix
でビルド
いくつか罠があって、
-
-Duser.home=$HOME
のように権限のある場所に一時ディレクトリを作って-Duser.home=$HOME
で指定しないと /var/empty にアクセスして Operation not permitted になって失敗する. 奇妙なことに JVM かプログラムが $HOME を無視していて -Duser.home で明示的に指定してやらないといけない. -
package --server=false
の-server=false
をつけないと bloop が /var/empty にアクセスしてこれまた Operation not permitted になる.
また、 bloop が動いているときは path が長すぎると unix domain too long のエラーが出て死ぬ.
nix の LSP 実装サーバー nil をインスコする
flake.nix の input に以下を追加
inputs = {
....
nil.url = "github:oxalica/nil";
....
output に nil をバインドする
outputs =
{ self, darwin, nixpkgs, nixpkgs-unstable, home-manager, nil, ... }@inputs:
overlays で nil を pkgs に含める
overlays = {
nil = final: prev: {
nil = nil.packages.${prev.stdenv.system}.nil;
};
nix build
する
vs code の場合、nix-ide エクステンションをインスコし以下の設定を追加する
"nix.enableLanguageServer": true,
"nix.serverPath": "nil",
"nix.serverSettings": {
"nil": {
"diagnostics": {
"ignored": [
"unused_binding",
"unused_with"
]
},
"formatting": {
"command": [
"nixfmt"
]
}
}
},
調べた中だと、satisfi のビルド周りが一番わかりやすい
Nix Flake でいい感じに Python の環境構築
{
description = "Flake to manage my Python workspace.";
inputs.nixpkgs.url = "nixpkgs/nixpkgs-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; };
# pkgs.python の withPackages が pkgs => [pythonPkgs] を受け取るのでここで定義する.
my-python-packages = ps:
with ps; [
pandas
numpy
jupyterlab
# nix 管理下にない PyPi パッケージを追加する.
(buildPythonPackage rec {
pname = "<パッケージ名>";
version = "0.7.5";
src = fetchPypi {
inherit pname version;
sha256 = "sha256-<適当な値を入れてクエリすると失敗と同時に実際の値が得られるのでそれを使う>";
};
doCheck = false;
# パッケージが依存するパッケージをここで指定する.
propagatedBuildInputs = [
pkgs.python310Packages.fsspe
];
})
];
in {
devShell = pkgs.mkShell {
name = "python-shell";
buildInputs = with pkgs; [
(python310.withPackages my-python-packages)
ruff
black
];
shellHook = ''
export PS1='\n\[\033[1;34m\][:\w]\$\[\033[0m\] '
'';
};
});
}
Nix flake でいい感じに Rust の環境構築
{
description = "Flake to manage Rust workspace.";
inputs.nixpkgs.url = "nixpkgs/nixpkgs-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.rust-overlay.url = "github:oxalica/rust-overlay";
outputs = { self, nixpkgs, rust-overlay, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs { inherit system overlays; };
in {
devShell = pkgs.mkShell {
name = "rust-shell";
buildInputs = with pkgs; [
rust-bin.beta.latest.default
cargo-udeps
iconv
rust-analyzer
];
};
});
}
Rust x nix flake
nix による構成管理
Docker 環境でのクロスビルド
kvm: kernel virtual machine とな? なぜかオプションがないとエラーになる.
sudo -i
がうまく動かない
以下の一連の作業で disk image が作れる.
git clone git@github.com:NixOS/nixpkgs.git && cd nixpkgs
git checkout nixos-22.11
https://nixos.wiki/wiki/Install_NixOS_on_GCE の指示に従ってイメージをビルドする. M1 Mac でやるので Docker を利用する.
cd ..
docker run --rm -it --platform=linux/amd64 -v `pwd`/nixpkgs:/nixpkgs --workdir /nixpkgs nixpkgs/nix:nixos-22.11 bash
gcloud sdk を利用するため一時的に unstable チャンネルを利用する. 作業が終わったら unset する.
NIX_PATH=nixpkgs=channel:nixos-unstable
nix-shell -p 'google-cloud-sdk'
export NIX_CONFIG=$'system-features = benchmark big-parallel nixos-test uid-range kvm\\nfilter-syscalls = false\\nexperimental-features = nix-command flakes'
上のオプションはトラブルシューティングしながら見つけた以下のサイトを参考にした.
- https://maulana.id/soft-dev/2023--08--22--00--running-nix-inside-docker-container-inside-apple-silicon/
- https://github.com/NixOS/nix/issues/5258
- https://github.com/nix-community/nixos-generators/issues/83
Google Storage bucket BUCKET_NAME
を作る.
BUCKET_NAME=nix-gce-img nixpkgs/nixos/maintainers/scripts/gce/create-gce.sh
NOTE:
GCS への up が失敗したら成果物に含まれる tar.gz を手動で gcs にアップロードしhttps://cloud.google.com/compute/docs/import/import-existing-image の指示に従ってイメージを作ればいい.
ここまで来ればイメージカラ GCE インスタンスを作成できる.
ssh で接続して動作確認する.
gcloud compute ssh --zone "<ZONE>" "<INSTANCE_NAME>" --project "<PROJECT>"
sudo -i
や をベースにいい感じのデプロイを組みたい.
network 周りのメモ
ゴールは nix-shell を使えるように public ip を公開しないでインターネットに接続する.
NAT を設定すればパブリックな ip アドレスがなくてもビルド時にインターネットアクセスできる.
ping はポートを指定できないので疎通確認は nc
で.
nc -v -w 1 <private ip> -z <port>
GCP の network の firewall rules のデフォルト
VPC が作成されると、いくつかのルートがシステムよって自動生成される. その中には 0.0.0.0/0 をデフォルトインターネットゲートウェイへ向けるルートも存在している.
ファイアウォールルールの項で解説したように、デフォルトでは下り (Egress) ルールは 0.0.0.0/0 に対し許可、上り (Ingress) では 0.0.0.0/0 からを拒否している
Identity aware proxy からのトラフィックは "35.235.240.0/20" からくるのでこれを許可しないと GCP のIAM認証を使ってインスタンスに接続できない.
resource "google_compute_firewall" "allow_ssh_traffic_via_iap" {
name = "allow-ssh-traffic-via-iap"
network = google_compute_network.hoge.name
priority = "65534"
direction = "INGRESS"
allow {
protocol = "tcp"
ports = ["22"]
}
source_ranges = [
"35.235.240.0/20"
]
}
これで nix-shell -p vim
などができるようになった.
次に以下のサイトを参考に flake を有効化する.
以下はインスタンスに flake を導入するためのミニマルな configuration.nix
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# Omit the previous configuration...
# Enable Flakes and the new command-line tool
nix.settings.experimental-features = [ "nix-command" "flakes" ];
environment.systemPackages = with pkgs; [
# Flakes use Git to pull dependencies from data sources
git
vim
wget
curl
];
# Set default editor to vim
environment.variables.EDITOR = "vim";
# Omit the rest of the configuration...
}
どこかの段階で configuration.nix や flake.nix をローカルに持ってきて git 管理・デプロイ自動化する方がいい.
memo:
export VERSION=0.1.0
gcloud compute scp foo-$VERSION.jar instance:/foo-$VERSION.jar
gcloud compute ssh -- (ここでfoo-$VERSION.jar を実行するプログラムに指定する処理を書く) && nixos-rebuild switch
とかすればできそう?
grpc-swift を nix derivation と flake で包む例.
nix flake ocaml
OCaml の Opam の代わりに nix を利用する例
flake.nix from ocaml riot-ml/bytestring
nix flake input url example
nix flake の inputs.*.url
の指定方法の例
builtins.fetchurl で s3 から取得することができる. nixpkgs.fetchurl とは全くの別物. nixpkgs.fetchurl は curl を呼び出す.
+------------------+-----------+--------------------------+------+
| systemd | ulimit | Description | Used |
+------------------+-----------+--------------------------+------+
| LimitCORE= | ulimit -c | core files size | Yes |
| LimitDATA= | ulimit -d | data segment size | No |
| LimitNICE= | ulimit -e | niceness level | Yes |
| LimitFSIZE= | ulimit -f | file size | No |
| LimitSIGPENDING= | ulimit -i | queued signals | Yes |
| LimitMEMLOCK= | ulimit -l | locked memory size | Yes |
| LimitRSS= | ulimit -m | resident set size | No |
| LimitNOFILE= | ulimit -n | open file descriptors | No |
| LimitMSGQUEUE= | ulimit -q | POSIX message queue size | Yes |
| LimitRTPRIO= | ulimit -r | real-time priority | Yes |
| LimitRTTIME= | ulimit -R | runtime before blocking | Yes |
| LimitSTACK= | ulimit -s | stack size | Yes |
| LimitCPU= | ulimit -t | CPU time | No |
| LimitNPROC= | ulimit -u | available processes | - |
| LimitAS= | ulimit -v | process virtual memory | No |
| LimitLOCKS= | ulimit -x | file lock count | Yes |
+------------------+-----------+--------------------------+------+