Compare commits
51 Commits
Author | SHA1 | Date |
---|---|---|
Emery Hemingway | 3cf46ea6e1 | |
Emery Hemingway | 51dbe15a13 | |
Emery Hemingway | 55d172ef30 | |
Emery Hemingway | 7ff5564d67 | |
Emery Hemingway | 6e31bf0b23 | |
Emery Hemingway | 266d09cad0 | |
Emery Hemingway | e1dd2b0aa4 | |
Emery Hemingway | 92e3850ab5 | |
Emery Hemingway | 2f6afc8d0b | |
Emery Hemingway | 81b52c46c7 | |
Emery Hemingway | ef8519aa34 | |
Emery Hemingway | 070e9a9da2 | |
Emery Hemingway | dc8c0f80eb | |
Emery Hemingway | 409a614010 | |
Emery Hemingway | cea8f719b8 | |
Emery Hemingway | 3f4c5ae37e | |
Emery Hemingway | a85b1cb618 | |
Emery Hemingway | e30bffdc72 | |
Emery Hemingway | a3ffae7da3 | |
Emery Hemingway | 53a6380759 | |
Emery Hemingway | 3d65eb0987 | |
Emery Hemingway | f75b35090e | |
Emery Hemingway | e905aada34 | |
Emery Hemingway | 327de24ea7 | |
Emery Hemingway | b7bf10234d | |
Emery Hemingway | 48d979dbe4 | |
Emery Hemingway | c8a9f38817 | |
Emery Hemingway | effbe05d2b | |
Emery Hemingway | b355f98b60 | |
Emery Hemingway | 513ca8420e | |
Emery Hemingway | 379840bea9 | |
Emery Hemingway | 50876967b1 | |
Emery Hemingway | b7af32fc66 | |
Emery Hemingway | 0ad63218fe | |
Emery Hemingway | 18c63d8619 | |
Emery Hemingway | 596580748f | |
Emery Hemingway | cecebbc118 | |
Emery Hemingway | 7fee5e35fe | |
Emery Hemingway | d243e63e9a | |
Emery Hemingway | a216ae43c4 | |
Emery Hemingway | 2dfd2ac52b | |
Emery Hemingway | e5ecb0ac26 | |
Emery Hemingway | 0e7ec9bb8a | |
Emery Hemingway | 51935e24db | |
Emery Hemingway | 2ad8fed971 | |
Emery Hemingway | ef8123e1a0 | |
Emery Hemingway | 666e30a8b1 | |
Emery Hemingway | 07893891ea | |
Emery Hemingway | 9d2342f5c1 | |
Emery Hemingway | 0f6d38dfa1 | |
Emery Hemingway | 2ea129e1a1 |
95
README.md
95
README.md
|
@ -2,57 +2,80 @@
|
|||
|
||||
To add to your local flake registry:
|
||||
```sh
|
||||
nix registry add syndicate "git+https://git.syndicate-lang.org/ehmry/syndicate-flake?ref=trunk"
|
||||
nix registry add syndicate "git+https://git.syndicate-lang.org/ehmry/syndicate-flake"
|
||||
```
|
||||
|
||||
## NixOS service
|
||||
## Synit
|
||||
|
||||
### Importing
|
||||
To import the NixOS module:
|
||||
```nix
|
||||
``` nix
|
||||
{
|
||||
# /etc/nixos/flake.nix
|
||||
inputs.syndicate.url = "git+https://git.syndicate-lang.org/ehmry/syndicate-flake?ref=trunk";
|
||||
description = "Personal NixOS configurations";
|
||||
|
||||
outputs = { self, nixpkgs, syndicate }: {
|
||||
inputs = {
|
||||
|
||||
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
syndicate.nixosModules.syndicate-server
|
||||
];
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
|
||||
syndicate = {
|
||||
url =
|
||||
"git+https://git.syndicate-lang.org/ehmry/syndicate-flake?ref=synit";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
```
|
||||
outputs = { self, nixpkgs, syndicate }:
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
overlays = [ syndicate.overlays.default ];
|
||||
in {
|
||||
|
||||
If `/etc/nixos` is not a flake then you may be able to use the `getFlake` builtin
|
||||
to retrieve the module.
|
||||
```nix
|
||||
{ config, lib, pkgs, ... }:
|
||||
legacyPackages =
|
||||
lib.attrsets.mapAttrs (system: pkgs: pkgs.appendOverlays overlays)
|
||||
nixpkgs.legacyPackages;
|
||||
|
||||
{
|
||||
imports = [ (builtins.getFlake "syndicate").nixosModules.syndicate-server ];
|
||||
}
|
||||
```
|
||||
nixosConfigurations = {
|
||||
|
||||
## Configuration
|
||||
```nix
|
||||
{ config, lib, pkgs, ... }:
|
||||
yourhost = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
|
||||
{
|
||||
services.syndicate-server = {
|
||||
enable = true;
|
||||
# A socket at /run/syndicate/ds is enable by default.
|
||||
tcpListeners = [{
|
||||
address = "127.0.0.1";
|
||||
port = 3232;
|
||||
}];
|
||||
};
|
||||
# A common bootloader
|
||||
{
|
||||
boot.loader = {
|
||||
efi.canTouchEfiVariables = false;
|
||||
grub = {
|
||||
enable = true;
|
||||
efiSupport = true;
|
||||
devices = [ "nodev" ];
|
||||
efiInstallAsRemovable = true;
|
||||
forceInstall = true;
|
||||
};
|
||||
systemd-boot.enable = false; # obviously not
|
||||
};
|
||||
}
|
||||
|
||||
# A normal NixOS system, the default boot profile.
|
||||
./your-normal-host-config/default.nix
|
||||
|
||||
# A Synit system nested inside and an alternative boot profile.
|
||||
{
|
||||
specialisation.synit = {
|
||||
inheritParentConfig = false; # keep it simple for now
|
||||
configuration = { config, ... }: {
|
||||
imports = [
|
||||
syndicate.nixosModules.synit
|
||||
./your-normal-host-config/hardware-configuration.nix
|
||||
];
|
||||
nixpkgs.pkgs = self.legacyPackages.${config.nixpkgs.system};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
```
|
||||
|
|
39
flake.lock
39
flake.lock
|
@ -2,11 +2,11 @@
|
|||
"nodes": {
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1623875721,
|
||||
"narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=",
|
||||
"lastModified": 1656928814,
|
||||
"narHash": "sha256-RIFfgBuKz6Hp89yRr7+NR5tzIAbn52h8vT6vXkYjZoM=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "f7e004a55b120c02ecb6219596820fcd32ca8772",
|
||||
"rev": "7e2a3b3dfd9af950a856d66b0a7d01e3c18aa249",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -17,31 +17,16 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1636723036,
|
||||
"narHash": "sha256-zFuu3TTj/NLq3NPJ8pprlmkOpjAoW3AWQNac3UFkCG8=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "50a1ef0f59752623af884f5085e3d5e8bd806c77",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "50a1ef0f59752623af884f5085e3d5e8bd806c77",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1628186154,
|
||||
"narHash": "sha256-r2d0wvywFnL9z4iptztdFMhaUIAaGzrSs7kSok0PgmE=",
|
||||
"lastModified": 1663157994,
|
||||
"narHash": "sha256-aHtdu/HuYImL59u1JbCLcHt26nMYsHRAuwHjlon2GVY=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "06552b72346632b6943c8032e57e702ea12413bf",
|
||||
"rev": "a083302d81557103200fd6f15ae4aba2ea0bafaa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "release-22.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
|
@ -55,14 +40,16 @@
|
|||
"rust": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1630548746,
|
||||
"narHash": "sha256-SLzeWhEN0kRDTzL+AHfDxwbYEZm09UEcdIcPDdOIZew=",
|
||||
"lastModified": 1663038100,
|
||||
"narHash": "sha256-DpqF/1FYpUo3Fm54oBaXzdqIG7BuRkHHFOgLM0uVVF0=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "00f6332f8c690480c7b7137fb8b1f069e7b2e18a",
|
||||
"rev": "dbd08f5b5469e1e24f00de45ddc73c26290a2bcb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
162
flake.nix
162
flake.nix
|
@ -1,38 +1,152 @@
|
|||
{
|
||||
description = "Syndicate utilities";
|
||||
|
||||
inputs.rust.url = "github:oxalica/rust-overlay";
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/release-22.05";
|
||||
inputs.rust = {
|
||||
url = "github:oxalica/rust-overlay";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
inputs.nixpkgs.url = "github:nixos/nixpkgs/50a1ef0f59752623af884f5085e3d5e8bd806c77";
|
||||
outputs = { self, nixpkgs, rust }: {
|
||||
lib = nixpkgs.lib.extend (import ./lib.nix);
|
||||
|
||||
outputs = { self, nixpkgs, rust }:
|
||||
let
|
||||
forEachSystem = nixpkgs.lib.genAttrs [ "aarch64-linux" "x86_64-linux" ];
|
||||
libOverlay = import ./lib.nix;
|
||||
in {
|
||||
lib = nixpkgs.lib.extend libOverlay;
|
||||
overlays.default = final: prev:
|
||||
let
|
||||
rust' =
|
||||
(prev.extend rust.overlays.default).rust-bin.nightly.latest.default;
|
||||
in {
|
||||
inherit (self) lib;
|
||||
|
||||
overlay = final: prev:
|
||||
let rust' = (prev.extend rust.overlay).rust-bin.nightly.latest.default;
|
||||
in {
|
||||
lib = prev.lib.extend libOverlay;
|
||||
preserves-nim = final.callPackage ./preserves-nim { };
|
||||
preserves-tools =
|
||||
final.callPackage ./preserves-tools { rust = rust'; };
|
||||
syndicate-rs = final.callPackage ./syndicate-rs { rust = rust'; };
|
||||
nimPackages = prev.nimPackages.overrideScope' (final': prev': {
|
||||
preserves = final'.callPackage ./packages/preserves-nim { };
|
||||
syndicate = final'.callPackage ./packages/syndicate-nim { };
|
||||
syndicate_utils =
|
||||
final'.callPackage ./packages/syndicate_utils-nim { };
|
||||
xdg_open_ng = final'.callPackage ./packages/xdg_open_ng { };
|
||||
});
|
||||
|
||||
python3Packages = prev.python3Packages.override {
|
||||
overrides = final': prev': {
|
||||
preserves = final'.callPackage ./packages/preserves-py { };
|
||||
syndicate = final'.callPackage ./packages/syndicate-py { };
|
||||
|
||||
synit-daemons = final'.callPackage ./packages/synit-daemons { };
|
||||
};
|
||||
};
|
||||
|
||||
packages = forEachSystem (system:
|
||||
let pkgs = nixpkgs.legacyPackages.${system}.extend self.overlay;
|
||||
in with pkgs; { inherit preserves-nim preserves-tools syndicate-rs; });
|
||||
preserves-tools =
|
||||
final.callPackage ./packages/preserves-tools { rust = rust'; };
|
||||
|
||||
nixosModules.syndicate-server =
|
||||
squeak = final.callPackage ./packages/squeak { };
|
||||
squeaker = final.python3Packages.callPackage ./packages/squeaker { };
|
||||
|
||||
syndicate-server =
|
||||
final.callPackage ./packages/syndicate-server { rust = rust'; };
|
||||
|
||||
synit-pid1 = final.callPackage ./packages/synit-pid1 { rust = rust'; };
|
||||
};
|
||||
|
||||
legacyPackages =
|
||||
self.lib.mapAttrs (system: pkgs: pkgs.extend self.overlays.default) {
|
||||
inherit (nixpkgs.legacyPackages) i686-linux x86_64-linux;
|
||||
};
|
||||
|
||||
packages = self.lib.mapAttrs (system: pkgs:
|
||||
with pkgs; {
|
||||
inherit preserves-tools squeak squeaker syndicate-server;
|
||||
inherit (nimPackages) syndicate_utils xdg_open_ng;
|
||||
preserves-nim = nimPackages.preserves;
|
||||
preserves-py = python3Packages.preserves;
|
||||
syndicate-nim = nimPackages.syndicate;
|
||||
syndicate-py = python3Packages.syndicate;
|
||||
}) self.legacyPackages;
|
||||
|
||||
nixosModules = {
|
||||
default = self.nixosModules.syndicate-server;
|
||||
|
||||
syndicate-server =
|
||||
# A little hack to apply our overlay to this module only.
|
||||
let f = import ./nixos/syndicate-server.nix;
|
||||
in { config, lib, pkgs, ... }:
|
||||
f {
|
||||
{ config, lib, pkgs, ... }:
|
||||
(import ./nixos/syndicate-server.nix) {
|
||||
inherit config lib;
|
||||
pkgs = pkgs.extend self.overlay;
|
||||
pkgs = pkgs.extend self.overlays.default;
|
||||
};
|
||||
|
||||
synit.imports = [
|
||||
./nixos/modules/system/boot/stage-1.nix
|
||||
./nixos/modules/system/boot/stage-2.nix
|
||||
./nixos/modules/system/boot/synit.nix
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
devShells = self.lib.mapAttrs (system: pkgs:
|
||||
with pkgs; {
|
||||
default =
|
||||
mkShell { packages = builtins.attrValues self.packages.${system}; };
|
||||
}) self.legacyPackages;
|
||||
|
||||
checks = self.lib.mapAttrs (system: pkgs':
|
||||
with import (nixpkgs + "/nixos/lib/testing-python.nix") {
|
||||
inherit system;
|
||||
pkgs = pkgs';
|
||||
}; {
|
||||
|
||||
http = simpleTest {
|
||||
nodes.machine = { config, pkgs, ... }: {
|
||||
imports = [ self.nixosModules.syndicate-server ];
|
||||
|
||||
nixpkgs.pkgs = pkgs';
|
||||
|
||||
services.syndicate.http = {
|
||||
enable = true;
|
||||
user = "nobody";
|
||||
config = [
|
||||
(pkgs.writeText "http.pr" ''
|
||||
<require-service <daemon http_translator>>
|
||||
|
||||
<daemon http_translator {
|
||||
argv: [ "${pkgs.nimPackages.syndicate_utils}/bin/http_translator" ]
|
||||
protocol: text/syndicate
|
||||
}>
|
||||
|
||||
let ?other = dataspace
|
||||
$other [
|
||||
? <http ?handle GET ?headers ?path ?body> [
|
||||
<http $handle 200 {} "Hello world!">
|
||||
]
|
||||
]
|
||||
|
||||
? <service-object <daemon http_translator> ?cap> $cap [
|
||||
<listen 8888>
|
||||
<handler #{GET} [ "greeting" ] $other>
|
||||
]
|
||||
'')
|
||||
];
|
||||
};
|
||||
|
||||
};
|
||||
testScript = ''
|
||||
machine.wait_for_job("syndicate-http")
|
||||
machine.wait_for_open_port(8888)
|
||||
machine.succeed("curl --fail http://localhost:8888/greeting")
|
||||
'';
|
||||
};
|
||||
|
||||
synit = simpleTest {
|
||||
nodes.machine = {
|
||||
imports = [
|
||||
self.nixosModules.synit
|
||||
];
|
||||
|
||||
nixpkgs.pkgs = pkgs';
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_unit("foo.service")
|
||||
'';
|
||||
};
|
||||
|
||||
}) { inherit (self.legacyPackages) x86_64-linux; };
|
||||
};
|
||||
}
|
||||
|
|
41
lib.nix
41
lib.nix
|
@ -5,14 +5,32 @@ in with lib; {
|
|||
generators = with final.generators;
|
||||
prev.generators // {
|
||||
|
||||
# Generates Preserves from an arbitrary value.
|
||||
# Records are generated for functions that take
|
||||
# a single formal argument `toRecord` and return
|
||||
# a list of values.
|
||||
/* Generates text-encoded Preserves from an arbitrary value.
|
||||
|
||||
Records are generated for lists with a final element in
|
||||
the form of `{ record = «label»; }`.
|
||||
|
||||
Type: toPreserves :: a -> string
|
||||
|
||||
Example:
|
||||
toPreserves { } [{ a = 0; b = 1; } "c" [ true false ] { record = "foo"; }]
|
||||
=> "<foo { a: 0 b: 1 } \"c\" [ #t #f ]>"
|
||||
*/
|
||||
toPreserves = { }@args:
|
||||
let
|
||||
toPreserves' = toPreserves args;
|
||||
concatItems = toString;
|
||||
recordLabel = list:
|
||||
with builtins;
|
||||
let len = length list;
|
||||
in if len == 0 then
|
||||
null
|
||||
else
|
||||
let end = elemAt list (len - 1);
|
||||
in if (isAttrs end) && (attrNames end) == [ "record" ] then
|
||||
end
|
||||
else
|
||||
null;
|
||||
in v:
|
||||
if isAttrs v then
|
||||
"{ ${
|
||||
|
@ -20,16 +38,17 @@ in with lib; {
|
|||
(key: val: "${key}: ${toPreserves' val}") v)
|
||||
} }"
|
||||
else if isList v then
|
||||
"[ ${concatItems (map toPreserves' v)} ]"
|
||||
let label = recordLabel v;
|
||||
in if label == null then
|
||||
"[ ${concatItems (map toPreserves' v)} ]"
|
||||
else
|
||||
"<${label.record} ${
|
||||
concatItems (map toPreserves' (lib.lists.init v))
|
||||
}>"
|
||||
else if isBool v then
|
||||
(if v then "#t" else "#f")
|
||||
else if isFunction v then
|
||||
(if (lib.functionArgs v) == { toRecord = false; } then
|
||||
let items = v { toRecord = null; };
|
||||
in "<${head items} ${toString (map toPreserves' (tail items))}>"
|
||||
else
|
||||
abort
|
||||
"generators.toPreserves: cannot convert a function to Preserves")
|
||||
abort "generators.toPreserves: cannot convert a function to Preserves"
|
||||
else if isNull v then
|
||||
"null"
|
||||
else
|
||||
|
|
|
@ -0,0 +1,626 @@
|
|||
#! @shell@
|
||||
|
||||
targetRoot=/mnt-root
|
||||
console=tty1
|
||||
verbose="@verbose@"
|
||||
|
||||
info() {
|
||||
if [[ -n "$verbose" ]]; then
|
||||
echo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
extraUtils="@extraUtils@"
|
||||
export LD_LIBRARY_PATH=@extraUtils@/lib
|
||||
export PATH=@extraUtils@/bin
|
||||
ln -s @extraUtils@/bin /bin
|
||||
|
||||
# Copy the secrets to their needed location
|
||||
if [ -d "@extraUtils@/secrets" ]; then
|
||||
for secret in $(cd "@extraUtils@/secrets"; find . -type f); do
|
||||
mkdir -p $(dirname "/$secret")
|
||||
ln -s "@extraUtils@/secrets/$secret" "$secret"
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
fail() {
|
||||
if [ -n "$panicOnFail" ]; then exit 1; fi
|
||||
|
||||
@preFailCommands@
|
||||
|
||||
# If starting stage 2 failed, allow the user to repair the problem
|
||||
# in an interactive shell.
|
||||
cat <<EOF
|
||||
|
||||
An error occurred in stage 1 of the boot process, which must mount the
|
||||
root filesystem on \`$targetRoot' and then start stage 2. Press one
|
||||
of the following keys:
|
||||
|
||||
EOF
|
||||
if [ -n "$allowShell" ]; then cat <<EOF
|
||||
i) to launch an interactive shell
|
||||
f) to start an interactive shell having pid 1 (needed if you want to
|
||||
start stage 2's init manually)
|
||||
EOF
|
||||
fi
|
||||
cat <<EOF
|
||||
r) to reboot immediately
|
||||
*) to ignore the error and continue
|
||||
EOF
|
||||
|
||||
read -n 1 reply
|
||||
|
||||
if [ -n "$allowShell" -a "$reply" = f ]; then
|
||||
exec setsid @shell@ -c "exec @shell@ < /dev/$console >/dev/$console 2>/dev/$console"
|
||||
elif [ -n "$allowShell" -a "$reply" = i ]; then
|
||||
echo "Starting interactive shell..."
|
||||
setsid @shell@ -c "exec @shell@ < /dev/$console >/dev/$console 2>/dev/$console" || fail
|
||||
elif [ "$reply" = r ]; then
|
||||
echo "Rebooting..."
|
||||
reboot -f
|
||||
else
|
||||
info "Continuing..."
|
||||
fi
|
||||
}
|
||||
|
||||
trap 'fail' 0
|
||||
|
||||
|
||||
# Print a greeting.
|
||||
info
|
||||
info "[1;32m<<< NixOS Stage 1 >>>[0m"
|
||||
info
|
||||
|
||||
# Make several required directories.
|
||||
mkdir -p /etc/udev
|
||||
touch /etc/fstab # to shut up mount
|
||||
ln -s /proc/mounts /etc/mtab # to shut up mke2fs
|
||||
touch /etc/udev/hwdb.bin # to shut up udev
|
||||
touch /etc/initrd-release
|
||||
|
||||
# Function for waiting for device(s) to appear.
|
||||
waitDevice() {
|
||||
local device="$1"
|
||||
# Split device string using ':' as a delimiter as bcachefs
|
||||
# uses this for multi-device filesystems, i.e. /dev/sda1:/dev/sda2:/dev/sda3
|
||||
local IFS=':'
|
||||
|
||||
# USB storage devices tend to appear with some delay. It would be
|
||||
# great if we had a way to synchronously wait for them, but
|
||||
# alas... So just wait for a few seconds for the device to
|
||||
# appear.
|
||||
for dev in $device; do
|
||||
if test ! -e $dev; then
|
||||
echo -n "waiting for device $dev to appear..."
|
||||
try=20
|
||||
while [ $try -gt 0 ]; do
|
||||
sleep 1
|
||||
udevadm trigger --action=add
|
||||
if test -e $dev; then break; fi
|
||||
echo -n "."
|
||||
try=$((try - 1))
|
||||
done
|
||||
echo
|
||||
[ $try -ne 0 ]
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Mount special file systems.
|
||||
specialMount() {
|
||||
local device="$1"
|
||||
local mountPoint="$2"
|
||||
local options="$3"
|
||||
local fsType="$4"
|
||||
|
||||
mkdir -m 0755 -p "$mountPoint"
|
||||
mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
|
||||
}
|
||||
source @earlyMountScript@
|
||||
|
||||
# Copy initrd secrets from /.initrd-secrets to their actual destinations
|
||||
if [ -d "/.initrd-secrets" ]; then
|
||||
#
|
||||
# Secrets are named by their full destination pathname and stored
|
||||
# under /.initrd-secrets/
|
||||
#
|
||||
for secret in $(cd "/.initrd-secrets"; find . -type f); do
|
||||
mkdir -p $(dirname "/$secret")
|
||||
cp "/.initrd-secrets/$secret" "$secret"
|
||||
done
|
||||
fi
|
||||
|
||||
# Log the script output to /dev/kmsg or /run/log/stage-1-init.log.
|
||||
mkdir -p /tmp
|
||||
mkfifo /tmp/stage-1-init.log.fifo
|
||||
logOutFd=8 && logErrFd=9
|
||||
eval "exec $logOutFd>&1 $logErrFd>&2"
|
||||
if test -w /dev/kmsg; then
|
||||
tee -i < /tmp/stage-1-init.log.fifo /proc/self/fd/"$logOutFd" | while read -r line; do
|
||||
if test -n "$line"; then
|
||||
echo "<7>stage-1-init: [$(date)] $line" > /dev/kmsg
|
||||
fi
|
||||
done &
|
||||
else
|
||||
mkdir -p /run/log
|
||||
tee -i < /tmp/stage-1-init.log.fifo /run/log/stage-1-init.log &
|
||||
fi
|
||||
exec > /tmp/stage-1-init.log.fifo 2>&1
|
||||
|
||||
|
||||
# Process the kernel command line.
|
||||
export stage2Init=/init
|
||||
for o in $(cat /proc/cmdline); do
|
||||
case $o in
|
||||
console=*)
|
||||
set -- $(IFS==; echo $o)
|
||||
params=$2
|
||||
set -- $(IFS=,; echo $params)
|
||||
console=$1
|
||||
;;
|
||||
init=*)
|
||||
set -- $(IFS==; echo $o)
|
||||
stage2Init=$2
|
||||
;;
|
||||
boot.persistence=*)
|
||||
set -- $(IFS==; echo $o)
|
||||
persistence=$2
|
||||
;;
|
||||
boot.persistence.opt=*)
|
||||
set -- $(IFS==; echo $o)
|
||||
persistence_opt=$2
|
||||
;;
|
||||
boot.trace|debugtrace)
|
||||
# Show each command.
|
||||
set -x
|
||||
;;
|
||||
boot.shell_on_fail)
|
||||
allowShell=1
|
||||
;;
|
||||
boot.debug1|debug1) # stop right away
|
||||
allowShell=1
|
||||
fail
|
||||
;;
|
||||
boot.debug1devices) # stop after loading modules and creating device nodes
|
||||
allowShell=1
|
||||
debug1devices=1
|
||||
;;
|
||||
boot.debug1mounts) # stop after mounting file systems
|
||||
allowShell=1
|
||||
debug1mounts=1
|
||||
;;
|
||||
boot.panic_on_fail|stage1panic=1)
|
||||
panicOnFail=1
|
||||
;;
|
||||
root=*)
|
||||
# If a root device is specified on the kernel command
|
||||
# line, make it available through the symlink /dev/root.
|
||||
# Recognise LABEL= and UUID= to support UNetbootin.
|
||||
set -- $(IFS==; echo $o)
|
||||
if [ $2 = "LABEL" ]; then
|
||||
root="/dev/disk/by-label/$3"
|
||||
elif [ $2 = "UUID" ]; then
|
||||
root="/dev/disk/by-uuid/$3"
|
||||
else
|
||||
root=$2
|
||||
fi
|
||||
ln -s "$root" /dev/root
|
||||
;;
|
||||
copytoram)
|
||||
copytoram=1
|
||||
;;
|
||||
findiso=*)
|
||||
# if an iso name is supplied, try to find the device where
|
||||
# the iso resides on
|
||||
set -- $(IFS==; echo $o)
|
||||
isoPath=$2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Set hostid before modules are loaded.
|
||||
# This is needed by the spl/zfs modules.
|
||||
@setHostId@
|
||||
|
||||
# Load the required kernel modules.
|
||||
mkdir -p /lib
|
||||
ln -s @modulesClosure@/lib/modules /lib/modules
|
||||
ln -s @modulesClosure@/lib/firmware /lib/firmware
|
||||
# see comment in stage-1.nix for explanation
|
||||
echo @extraUtils@/bin/modprobe-kernel > /proc/sys/kernel/modprobe
|
||||
for i in @kernelModules@; do
|
||||
info "loading module $(basename $i)..."
|
||||
modprobe $i
|
||||
done
|
||||
|
||||
|
||||
# Create device nodes in /dev.
|
||||
@preDeviceCommands@
|
||||
info "running udev..."
|
||||
ln -sfn /proc/self/fd /dev/fd
|
||||
ln -sfn /proc/self/fd/0 /dev/stdin
|
||||
ln -sfn /proc/self/fd/1 /dev/stdout
|
||||
ln -sfn /proc/self/fd/2 /dev/stderr
|
||||
mkdir -p /etc/udev
|
||||
ln -sfn @udevRules@ /etc/udev/rules.d
|
||||
mkdir -p /dev/.mdadm
|
||||
udevd --daemon
|
||||
udevadm trigger --action=add
|
||||
udevadm settle
|
||||
|
||||
|
||||
if test -n "$debug1devices"; then fail; fi
|
||||
|
||||
|
||||
@postDeviceCommands@
|
||||
|
||||
|
||||
# Check the specified file system, if appropriate.
|
||||
checkFS() {
|
||||
local device="$1"
|
||||
local fsType="$2"
|
||||
|
||||
# Only check block devices.
|
||||
if [ ! -b "$device" ]; then return 0; fi
|
||||
|
||||
# Don't check ROM filesystems.
|
||||
if [ "$fsType" = iso9660 -o "$fsType" = udf ]; then return 0; fi
|
||||
|
||||
# Don't check resilient COWs as they validate the fs structures at mount time
|
||||
if [ "$fsType" = btrfs -o "$fsType" = zfs -o "$fsType" = bcachefs ]; then return 0; fi
|
||||
|
||||
# Skip fsck for apfs as the fsck utility does not support repairing the filesystem (no -a option)
|
||||
if [ "$fsType" = apfs ]; then return 0; fi
|
||||
|
||||
# Skip fsck for nilfs2 - not needed by design and no fsck tool for this filesystem.
|
||||
if [ "$fsType" = nilfs2 ]; then return 0; fi
|
||||
|
||||
# Skip fsck for inherently readonly filesystems.
|
||||
if [ "$fsType" = squashfs ]; then return 0; fi
|
||||
|
||||
# If we couldn't figure out the FS type, then skip fsck.
|
||||
if [ "$fsType" = auto ]; then
|
||||
echo 'cannot check filesystem with type "auto"!'
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Device might be already mounted manually
|
||||
# e.g. NBD-device or the host filesystem of the file which contains encrypted root fs
|
||||
if mount | grep -q "^$device on "; then
|
||||
echo "skip checking already mounted $device"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Optionally, skip fsck on journaling filesystems. This option is
|
||||
# a hack - it's mostly because e2fsck on ext3 takes much longer to
|
||||
# recover the journal than the ext3 implementation in the kernel
|
||||
# does (minutes versus seconds).
|
||||
if test -z "@checkJournalingFS@" -a \
|
||||
\( "$fsType" = ext3 -o "$fsType" = ext4 -o "$fsType" = reiserfs \
|
||||
-o "$fsType" = xfs -o "$fsType" = jfs -o "$fsType" = f2fs \)
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "checking $device..."
|
||||
|
||||
fsck -V -a "$device"
|
||||
fsckResult=$?
|
||||
|
||||
if test $(($fsckResult | 2)) = $fsckResult; then
|
||||
echo "fsck finished, rebooting..."
|
||||
sleep 3
|
||||
reboot -f
|
||||
fi
|
||||
|
||||
if test $(($fsckResult | 4)) = $fsckResult; then
|
||||
echo "$device has unrepaired errors, please fix them manually."
|
||||
fail
|
||||
fi
|
||||
|
||||
if test $fsckResult -ge 8; then
|
||||
echo "fsck on $device failed."
|
||||
fail
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
# Function for mounting a file system.
|
||||
mountFS() {
|
||||
local device="$1"
|
||||
local mountPoint="$2"
|
||||
local options="$3"
|
||||
local fsType="$4"
|
||||
|
||||
if [ "$fsType" = auto ]; then
|
||||
fsType=$(blkid -o value -s TYPE "$device")
|
||||
if [ -z "$fsType" ]; then fsType=auto; fi
|
||||
fi
|
||||
|
||||
# Filter out x- options, which busybox doesn't do yet.
|
||||
local optionsFiltered="$(IFS=,; for i in $options; do if [ "${i:0:2}" != "x-" ]; then echo -n $i,; fi; done)"
|
||||
# Prefix (lower|upper|work)dir with /mnt-root (overlayfs)
|
||||
local optionsPrefixed="$( echo "$optionsFiltered" | sed -E 's#\<(lowerdir|upperdir|workdir)=#\1=/mnt-root#g' )"
|
||||
|
||||
echo "$device /mnt-root$mountPoint $fsType $optionsPrefixed" >> /etc/fstab
|
||||
|
||||
checkFS "$device" "$fsType"
|
||||
|
||||
# Optionally resize the filesystem.
|
||||
case $options in
|
||||
*x-nixos.autoresize*)
|
||||
if [ "$fsType" = ext2 -o "$fsType" = ext3 -o "$fsType" = ext4 ]; then
|
||||
modprobe "$fsType"
|
||||
echo "resizing $device..."
|
||||
e2fsck -fp "$device"
|
||||
resize2fs "$device"
|
||||
elif [ "$fsType" = f2fs ]; then
|
||||
echo "resizing $device..."
|
||||
fsck.f2fs -fp "$device"
|
||||
resize.f2fs "$device"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Create backing directories for overlayfs
|
||||
if [ "$fsType" = overlay ]; then
|
||||
for i in upper work; do
|
||||
dir="$( echo "$optionsPrefixed" | grep -o "${i}dir=[^,]*" )"
|
||||
mkdir -m 0700 -p "${dir##*=}"
|
||||
done
|
||||
fi
|
||||
|
||||
info "mounting $device on $mountPoint..."
|
||||
|
||||
mkdir -p "/mnt-root$mountPoint"
|
||||
|
||||
# For ZFS and CIFS mounts, retry a few times before giving up.
|
||||
# We do this for ZFS as a workaround for issue NixOS/nixpkgs#25383.
|
||||
local n=0
|
||||
while true; do
|
||||
mount "/mnt-root$mountPoint" && break
|
||||
if [ \( "$fsType" != cifs -a "$fsType" != zfs \) -o "$n" -ge 10 ]; then fail; break; fi
|
||||
echo "retrying..."
|
||||
sleep 1
|
||||
n=$((n + 1))
|
||||
done
|
||||
|
||||
[ "$mountPoint" == "/" ] &&
|
||||
[ -f "/mnt-root/etc/NIXOS_LUSTRATE" ] &&
|
||||
lustrateRoot "/mnt-root"
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
lustrateRoot () {
|
||||
local root="$1"
|
||||
|
||||
echo
|
||||
echo -e "\e[1;33m<<< NixOS is now lustrating the root filesystem (cruft goes to /old-root) >>>\e[0m"
|
||||
echo
|
||||
|
||||
mkdir -m 0755 -p "$root/old-root.tmp"
|
||||
|
||||
echo
|
||||
echo "Moving impurities out of the way:"
|
||||
for d in "$root"/*
|
||||
do
|
||||
[ "$d" == "$root/nix" ] && continue
|
||||
[ "$d" == "$root/boot" ] && continue # Don't render the system unbootable
|
||||
[ "$d" == "$root/old-root.tmp" ] && continue
|
||||
|
||||
mv -v "$d" "$root/old-root.tmp"
|
||||
done
|
||||
|
||||
# Use .tmp to make sure subsequent invokations don't clash
|
||||
mv -v "$root/old-root.tmp" "$root/old-root"
|
||||
|
||||
mkdir -m 0755 -p "$root/etc"
|
||||
touch "$root/etc/NIXOS"
|
||||
|
||||
exec 4< "$root/old-root/etc/NIXOS_LUSTRATE"
|
||||
|
||||
echo
|
||||
echo "Restoring selected impurities:"
|
||||
while read -u 4 keeper; do
|
||||
dirname="$(dirname "$keeper")"
|
||||
mkdir -m 0755 -p "$root/$dirname"
|
||||
cp -av "$root/old-root/$keeper" "$root/$keeper"
|
||||
done
|
||||
|
||||
exec 4>&-
|
||||
}
|
||||
|
||||
|
||||
|
||||
if test -e /sys/power/resume -a -e /sys/power/disk; then
|
||||
if test -n "@resumeDevice@" && waitDevice "@resumeDevice@"; then
|
||||
resumeDev="@resumeDevice@"
|
||||
resumeInfo="$(udevadm info -q property "$resumeDev" )"
|
||||
else
|
||||
for sd in @resumeDevices@; do
|
||||
# Try to detect resume device. According to Ubuntu bug:
|
||||
# https://bugs.launchpad.net/ubuntu/+source/pm-utils/+bug/923326/comments/1
|
||||
# when there are multiple swap devices, we can't know where the hibernate
|
||||
# image will reside. We can check all of them for swsuspend blkid.
|
||||
if waitDevice "$sd"; then
|
||||
resumeInfo="$(udevadm info -q property "$sd")"
|
||||
if [ "$(echo "$resumeInfo" | sed -n 's/^ID_FS_TYPE=//p')" = "swsuspend" ]; then
|
||||
resumeDev="$sd"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test -n "$resumeDev"; then
|
||||
resumeMajor="$(echo "$resumeInfo" | sed -n 's/^MAJOR=//p')"
|
||||
resumeMinor="$(echo "$resumeInfo" | sed -n 's/^MINOR=//p')"
|
||||
echo "$resumeMajor:$resumeMinor" > /sys/power/resume 2> /dev/null || echo "failed to resume..."
|
||||
fi
|
||||
fi
|
||||
|
||||
# If we have a path to an iso file, find the iso and link it to /dev/root
|
||||
if [ -n "$isoPath" ]; then
|
||||
mkdir -p /findiso
|
||||
|
||||
for delay in 5 10; do
|
||||
blkid | while read -r line; do
|
||||
device=$(echo "$line" | sed 's/:.*//')
|
||||
type=$(echo "$line" | sed 's/.*TYPE="\([^"]*\)".*/\1/')
|
||||
|
||||
mount -t "$type" "$device" /findiso
|
||||
if [ -e "/findiso$isoPath" ]; then
|
||||
ln -sf "/findiso$isoPath" /dev/root
|
||||
break 2
|
||||
else
|
||||
umount /findiso
|
||||
fi
|
||||
done
|
||||
|
||||
sleep "$delay"
|
||||
done
|
||||
fi
|
||||
|
||||
# Try to find and mount the root device.
|
||||
mkdir -p $targetRoot
|
||||
|
||||
exec 3< @fsInfo@
|
||||
|
||||
while read -u 3 mountPoint; do
|
||||
read -u 3 device
|
||||
read -u 3 fsType
|
||||
read -u 3 options
|
||||
|
||||
# !!! Really quick hack to support bind mounts, i.e., where the
|
||||
# "device" should be taken relative to /mnt-root, not /. Assume
|
||||
# that every device that starts with / but doesn't start with /dev
|
||||
# is a bind mount.
|
||||
pseudoDevice=
|
||||
case $device in
|
||||
/dev/*)
|
||||
;;
|
||||
//*)
|
||||
# Don't touch SMB/CIFS paths.
|
||||
pseudoDevice=1
|
||||
;;
|
||||
/*)
|
||||
device=/mnt-root$device
|
||||
;;
|
||||
*)
|
||||
# Not an absolute path; assume that it's a pseudo-device
|
||||
# like an NFS path (e.g. "server:/path").
|
||||
pseudoDevice=1
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -z "$pseudoDevice" && ! waitDevice "$device"; then
|
||||
# If it doesn't appear, try to mount it anyway (and
|
||||
# probably fail). This is a fallback for non-device "devices"
|
||||
# that we don't properly recognise.
|
||||
echo "Timed out waiting for device $device, trying to mount anyway."
|
||||
fi
|
||||
|
||||
# Wait once more for the udev queue to empty, just in case it's
|
||||
# doing something with $device right now.
|
||||
udevadm settle
|
||||
|
||||
# If copytoram is enabled: skip mounting the ISO and copy its content to a tmpfs.
|
||||
if [ -n "$copytoram" ] && [ "$device" = /dev/root ] && [ "$mountPoint" = /iso ]; then
|
||||
fsType=$(blkid -o value -s TYPE "$device")
|
||||
fsSize=$(blockdev --getsize64 "$device" || stat -Lc '%s' "$device")
|
||||
|
||||
mkdir -p /tmp-iso
|
||||
mount -t "$fsType" /dev/root /tmp-iso
|
||||
mountFS tmpfs /iso size="$fsSize" tmpfs
|
||||
|
||||
cp -r /tmp-iso/* /mnt-root/iso/
|
||||
|
||||
umount /tmp-iso
|
||||
rmdir /tmp-iso
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ "$mountPoint" = / ] && [ "$device" = tmpfs ] && [ ! -z "$persistence" ]; then
|
||||
echo persistence...
|
||||
waitDevice "$persistence"
|
||||
echo enabling persistence...
|
||||
mountFS "$persistence" "$mountPoint" "$persistence_opt" "auto"
|
||||
continue
|
||||
fi
|
||||
|
||||
mountFS "$device" "$mountPoint" "$options" "$fsType"
|
||||
done
|
||||
|
||||
exec 3>&-
|
||||
|
||||
|
||||
@postMountCommands@
|
||||
|
||||
|
||||
# Emit a udev rule for /dev/root to prevent systemd from complaining.
|
||||
if [ -e /mnt-root/iso ]; then
|
||||
eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=/mnt-root/iso)
|
||||
else
|
||||
eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=$targetRoot)
|
||||
fi
|
||||
if [ "$ROOT_MAJOR" -a "$ROOT_MINOR" -a "$ROOT_MAJOR" != 0 ]; then
|
||||
mkdir -p /run/udev/rules.d
|
||||
echo 'ACTION=="add|change", SUBSYSTEM=="block", ENV{MAJOR}=="'$ROOT_MAJOR'", ENV{MINOR}=="'$ROOT_MINOR'", SYMLINK+="root"' > /run/udev/rules.d/61-dev-root-link.rules
|
||||
fi
|
||||
|
||||
|
||||
# Stop udevd.
|
||||
udevadm control --exit
|
||||
|
||||
# Reset the logging file descriptors.
|
||||
# Do this just before pkill, which will kill the tee process.
|
||||
exec 1>&$logOutFd 2>&$logErrFd
|
||||
eval "exec $logOutFd>&- $logErrFd>&-"
|
||||
|
||||
# Kill any remaining processes, just to be sure we're not taking any
|
||||
# with us into stage 2. But keep storage daemons like unionfs-fuse.
|
||||
#
|
||||
# Storage daemons are distinguished by an @ in front of their command line:
|
||||
# https://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons/
|
||||
for pid in $(pgrep -v -f '^@'); do
|
||||
# Make sure we don't kill kernel processes, see #15226 and:
|
||||
# http://stackoverflow.com/questions/12213445/identifying-kernel-threads
|
||||
readlink "/proc/$pid/exe" &> /dev/null || continue
|
||||
# Try to avoid killing ourselves.
|
||||
[ $pid -eq $$ ] && continue
|
||||
kill -9 "$pid"
|
||||
done
|
||||
|
||||
if test -n "$debug1mounts"; then fail; fi
|
||||
|
||||
|
||||
# Restore /proc/sys/kernel/modprobe to its original value.
|
||||
echo /sbin/modprobe > /proc/sys/kernel/modprobe
|
||||
|
||||
|
||||
# Start stage 2. `switch_root' deletes all files in the ramfs on the
|
||||
# current root. The path has to be valid in the chroot not outside.
|
||||
if [ ! -e "$targetRoot/$stage2Init" ]; then
|
||||
stage2Check=${stage2Init}
|
||||
while [ "$stage2Check" != "${stage2Check%/*}" ] && [ ! -L "$targetRoot/$stage2Check" ]; do
|
||||
stage2Check=${stage2Check%/*}
|
||||
done
|
||||
if [ ! -L "$targetRoot/$stage2Check" ]; then
|
||||
echo "stage 2 init script ($targetRoot/$stage2Init) not found"
|
||||
fail
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -m 0755 -p $targetRoot/proc $targetRoot/sys $targetRoot/dev $targetRoot/run
|
||||
|
||||
mount --move /proc $targetRoot/proc
|
||||
mount --move /sys $targetRoot/sys
|
||||
mount --move /dev $targetRoot/dev
|
||||
mount --move /run $targetRoot/run
|
||||
|
||||
exec env -i $(type -P switch_root) "$targetRoot" "$stage2Init"
|
||||
|
||||
fail # should never be reached
|
|
@ -0,0 +1,427 @@
|
|||
# This module builds the initial ramdisk, which contains an init
|
||||
# script that performs the first stage of booting the system: it loads
|
||||
# the modules necessary to mount the root file system, then calls the
|
||||
# init in the root file system to start the second boot stage.
|
||||
|
||||
{ config, lib, utils, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
udev = pkgs.eudev;
|
||||
|
||||
kernel-name = config.boot.kernelPackages.kernel.name or "kernel";
|
||||
|
||||
modulesTree = config.system.modulesTree.override { name = kernel-name + "-modules"; };
|
||||
firmware = config.hardware.firmware;
|
||||
|
||||
|
||||
# Determine the set of modules that we need to mount the root FS.
|
||||
modulesClosure = pkgs.makeModulesClosure {
|
||||
rootModules = config.boot.initrd.availableKernelModules ++ config.boot.initrd.kernelModules;
|
||||
kernel = modulesTree;
|
||||
firmware = firmware;
|
||||
allowMissing = false;
|
||||
};
|
||||
|
||||
|
||||
# The initrd only has to mount `/` or any FS marked as necessary for
|
||||
# booting (such as the FS containing `/nix/store`, or an FS needed for
|
||||
# mounting `/`, like `/` on a loopback).
|
||||
fileSystems = filter utils.fsNeededForBoot config.system.build.fileSystems;
|
||||
|
||||
# A utility for enumerating the shared-library dependencies of a program
|
||||
findLibs = pkgs.buildPackages.writeShellScriptBin "find-libs" ''
|
||||
set -euo pipefail
|
||||
|
||||
declare -A seen
|
||||
left=()
|
||||
|
||||
patchelf="${pkgs.buildPackages.patchelf}/bin/patchelf"
|
||||
|
||||
function add_needed {
|
||||
rpath="$($patchelf --print-rpath $1)"
|
||||
dir="$(dirname $1)"
|
||||
for lib in $($patchelf --print-needed $1); do
|
||||
left+=("$lib" "$rpath" "$dir")
|
||||
done
|
||||
}
|
||||
|
||||
add_needed "$1"
|
||||
|
||||
while [ ''${#left[@]} -ne 0 ]; do
|
||||
next=''${left[0]}
|
||||
rpath=''${left[1]}
|
||||
ORIGIN=''${left[2]}
|
||||
left=("''${left[@]:3}")
|
||||
if [ -z ''${seen[$next]+x} ]; then
|
||||
seen[$next]=1
|
||||
|
||||
# Ignore the dynamic linker which for some reason appears as a DT_NEEDED of glibc but isn't in glibc's RPATH.
|
||||
case "$next" in
|
||||
ld*.so.?) continue;;
|
||||
esac
|
||||
|
||||
IFS=: read -ra paths <<< $rpath
|
||||
res=
|
||||
for path in "''${paths[@]}"; do
|
||||
path=$(eval "echo $path")
|
||||
if [ -f "$path/$next" ]; then
|
||||
res="$path/$next"
|
||||
echo "$res"
|
||||
add_needed "$res"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "$res" ]; then
|
||||
echo "Couldn't satisfy dependency $next" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
'';
|
||||
|
||||
# Some additional utilities needed in stage 1, like mount, fsck
|
||||
# etc. We don't want to bring in all of those packages, so we just
|
||||
# copy what we need. Instead of using statically linked binaries,
|
||||
# we just copy what we need from Glibc and use patchelf to make it
|
||||
# work.
|
||||
extraUtils = pkgs.runCommandCC "extra-utils"
|
||||
{ nativeBuildInputs = [pkgs.buildPackages.nukeReferences];
|
||||
allowedReferences = [ "out" ]; # prevent accidents like glibc being included in the initrd
|
||||
}
|
||||
''
|
||||
set +o pipefail
|
||||
|
||||
mkdir -p $out/bin $out/lib
|
||||
ln -s $out/bin $out/sbin
|
||||
|
||||
copy_bin_and_libs () {
|
||||
[ -f "$out/bin/$(basename $1)" ] && rm "$out/bin/$(basename $1)"
|
||||
cp -pdv $1 $out/bin
|
||||
}
|
||||
|
||||
# Copy BusyBox.
|
||||
for BIN in ${pkgs.busybox}/{s,}bin/*; do
|
||||
copy_bin_and_libs $BIN
|
||||
done
|
||||
|
||||
# Copy some util-linux stuff.
|
||||
copy_bin_and_libs ${pkgs.util-linux}/sbin/blkid
|
||||
|
||||
# Add RAID mdadm tool.
|
||||
copy_bin_and_libs ${pkgs.mdadm}/sbin/mdadm
|
||||
copy_bin_and_libs ${pkgs.mdadm}/sbin/mdmon
|
||||
|
||||
# Copy udev.
|
||||
copy_bin_and_libs ${udev}/bin/udevd
|
||||
copy_bin_and_libs ${udev}/bin/udevadm
|
||||
for BIN in ${udev}/lib/udev/*_id; do
|
||||
copy_bin_and_libs $BIN
|
||||
done
|
||||
|
||||
# Copy modprobe.
|
||||
copy_bin_and_libs ${pkgs.kmod}/bin/kmod
|
||||
ln -sf kmod $out/bin/modprobe
|
||||
|
||||
# Dirty hack to make sure the kernel properly loads modules
|
||||
# such as ext4 on demand (e.g. on a `mount(2)` syscall). This is necessary
|
||||
# because `kmod` isn't linked against `libpthread.so.0` anymore (since
|
||||
# it was merged into `libc.so.6` since version `2.34`), but still needs
|
||||
# to access it for some reason. This is not an issue in stage-1 itself
|
||||
# because of the `LD_LIBRARY_PATH`-variable and anytime later because the rpath of
|
||||
# kmod/modprobe points to glibc's `$out/lib` where `libpthread.so.6` exists.
|
||||
# However, this is a problem when the kernel calls `modprobe` inside
|
||||
# the initial ramdisk because it doesn't know about the
|
||||
# `LD_LIBRARY_PATH` and the rpath was nuked.
|
||||
#
|
||||
# Also, we can't use `makeWrapper` here because `kmod` only does
|
||||
# `modprobe` functionality if `argv[0] == "modprobe"`.
|
||||
cat >$out/bin/modprobe-kernel <<EOF
|
||||
#!$out/bin/ash
|
||||
export LD_LIBRARY_PATH=$out/lib
|
||||
exec $out/bin/modprobe "\$@"
|
||||
EOF
|
||||
chmod +x $out/bin/modprobe-kernel
|
||||
|
||||
# Copy resize2fs if any ext* filesystems are to be resized
|
||||
${optionalString (any (fs: fs.autoResize && (lib.hasPrefix "ext" fs.fsType)) fileSystems) ''
|
||||
# We need mke2fs in the initrd.
|
||||
copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/resize2fs
|
||||
''}
|
||||
|
||||
# Copy multipath.
|
||||
${optionalString config.services.multipath.enable ''
|
||||
copy_bin_and_libs ${config.services.multipath.package}/bin/multipath
|
||||
copy_bin_and_libs ${config.services.multipath.package}/bin/multipathd
|
||||
# Copy lib/multipath manually.
|
||||
cp -rpv ${config.services.multipath.package}/lib/multipath $out/lib
|
||||
''}
|
||||
|
||||
# Copy secrets if needed.
|
||||
#
|
||||
# TODO: move out to a separate script; see #85000.
|
||||
${optionalString (!config.boot.loader.supportsInitrdSecrets)
|
||||
(concatStringsSep "\n" (mapAttrsToList (dest: source:
|
||||
let source' = if source == null then dest else source; in
|
||||
''
|
||||
mkdir -p $(dirname "$out/secrets/${dest}")
|
||||
# Some programs (e.g. ssh) doesn't like secrets to be
|
||||
# symlinks, so we use `cp -L` here to match the
|
||||
# behaviour when secrets are natively supported.
|
||||
cp -Lr ${source'} "$out/secrets/${dest}"
|
||||
''
|
||||
) config.boot.initrd.secrets))
|
||||
}
|
||||
|
||||
${config.boot.initrd.extraUtilsCommands}
|
||||
|
||||
# Copy ld manually since it isn't detected correctly
|
||||
cp -pv ${pkgs.stdenv.cc.libc.out}/lib/ld*.so.? $out/lib
|
||||
|
||||
# Copy all of the needed libraries
|
||||
find $out/bin $out/lib -type f | while read BIN; do
|
||||
echo "Copying libs for executable $BIN"
|
||||
for LIB in $(${findLibs}/bin/find-libs $BIN); do
|
||||
TGT="$out/lib/$(basename $LIB)"
|
||||
if [ ! -f "$TGT" ]; then
|
||||
SRC="$(readlink -e $LIB)"
|
||||
cp -pdv "$SRC" "$TGT"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Strip binaries further than normal.
|
||||
chmod -R u+w $out
|
||||
stripDirs "$STRIP" "lib bin" "-s"
|
||||
|
||||
# Run patchelf to make the programs refer to the copied libraries.
|
||||
find $out/bin $out/lib -type f | while read i; do
|
||||
if ! test -L $i; then
|
||||
nuke-refs -e $out $i
|
||||
fi
|
||||
done
|
||||
|
||||
find $out/bin -type f | while read i; do
|
||||
if ! test -L $i; then
|
||||
echo "patching $i..."
|
||||
patchelf --set-interpreter $out/lib/ld*.so.? --set-rpath $out/lib $i || true
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "${toString (pkgs.stdenv.hostPlatform != pkgs.stdenv.buildPlatform)}" ]; then
|
||||
# Make sure that the patchelf'ed binaries still work.
|
||||
echo "testing patched programs..."
|
||||
$out/bin/ash -c 'echo hello world' | grep "hello world"
|
||||
export LD_LIBRARY_PATH=$out/lib
|
||||
$out/bin/mount --help 2>&1 | grep -q "BusyBox"
|
||||
$out/bin/blkid -V 2>&1 | grep -q 'libblkid'
|
||||
$out/bin/udevadm --version
|
||||
$out/bin/mdadm --version
|
||||
${optionalString config.services.multipath.enable ''
|
||||
($out/bin/multipath || true) 2>&1 | grep -q 'need to be root'
|
||||
($out/bin/multipathd || true) 2>&1 | grep -q 'need to be root'
|
||||
''}
|
||||
|
||||
${config.boot.initrd.extraUtilsCommandsTest}
|
||||
fi
|
||||
''; # */
|
||||
|
||||
udevRules = pkgs.runCommand "udev-rules" {
|
||||
allowedReferences = [ extraUtils ];
|
||||
preferLocalBuild = true;
|
||||
} ''
|
||||
mkdir -p $out
|
||||
|
||||
echo 'ENV{LD_LIBRARY_PATH}="${extraUtils}/lib"' > $out/00-env.rules
|
||||
|
||||
cp -v ${udev}/var/lib/udev/rules.d/60-cdrom_id.rules $out/
|
||||
cp -v ${udev}/var/lib/udev/rules.d/60-persistent-storage.rules $out/
|
||||
cp -v ${udev}/var/lib/udev/rules.d/75-net-description.rules $out/
|
||||
cp -v ${udev}/var/lib/udev/rules.d/80-drivers.rules $out/
|
||||
cp -v ${udev}/var/lib/udev/rules.d/80-net-name-slot.rules $out/
|
||||
${config.boot.initrd.extraUdevRulesCommands}
|
||||
|
||||
for i in $out/*.rules; do
|
||||
substituteInPlace $i \
|
||||
--replace ata_id ${extraUtils}/bin/ata_id \
|
||||
--replace scsi_id ${extraUtils}/bin/scsi_id \
|
||||
--replace cdrom_id ${extraUtils}/bin/cdrom_id \
|
||||
--replace ${pkgs.coreutils}/bin/basename ${extraUtils}/bin/basename \
|
||||
--replace ${pkgs.util-linux}/bin/blkid ${extraUtils}/bin/blkid \
|
||||
--replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \
|
||||
--replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \
|
||||
--replace ${udev} ${extraUtils}
|
||||
done
|
||||
|
||||
# Work around a bug in QEMU, which doesn't implement the "READ
|
||||
# DISC INFORMATION" SCSI command:
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=609049
|
||||
# As a result, `cdrom_id' doesn't print
|
||||
# ID_CDROM_MEDIA_TRACK_COUNT_DATA, which in turn prevents the
|
||||
# /dev/disk/by-label symlinks from being created. We need these
|
||||
# in the NixOS installation CD, so use ID_CDROM_MEDIA in the
|
||||
# corresponding udev rules for now. This was the behaviour in
|
||||
# udev <= 154. See also
|
||||
# http://www.spinics.net/lists/hotplug/msg03935.html
|
||||
substituteInPlace $out/60-persistent-storage.rules \
|
||||
--replace ID_CDROM_MEDIA_TRACK_COUNT_DATA ID_CDROM_MEDIA
|
||||
''; # */
|
||||
|
||||
|
||||
# The init script of boot stage 1 (loading kernel modules for
|
||||
# mounting the root FS).
|
||||
bootStage1 = pkgs.substituteAll {
|
||||
src = ./stage-1-init.sh;
|
||||
|
||||
shell = "${extraUtils}/bin/ash";
|
||||
|
||||
isExecutable = true;
|
||||
|
||||
postInstall = ''
|
||||
echo checking syntax
|
||||
# check both with bash
|
||||
${pkgs.buildPackages.bash}/bin/sh -n $target
|
||||
# and with ash shell, just in case
|
||||
${pkgs.buildPackages.busybox}/bin/ash -n $target
|
||||
'';
|
||||
|
||||
inherit udevRules extraUtils modulesClosure;
|
||||
|
||||
inherit (config.boot) resumeDevice;
|
||||
|
||||
inherit (config.system.build) earlyMountScript;
|
||||
|
||||
inherit (config.boot.initrd) checkJournalingFS verbose
|
||||
preDeviceCommands postDeviceCommands postMountCommands preFailCommands kernelModules;
|
||||
|
||||
resumeDevices = map (sd: if sd ? device then sd.device else "/dev/disk/by-label/${sd.label}")
|
||||
(filter (sd: hasPrefix "/dev/" sd.device && !sd.randomEncryption.enable
|
||||
# Don't include zram devices
|
||||
&& !(hasPrefix "/dev/zram" sd.device)
|
||||
) config.swapDevices);
|
||||
|
||||
fsInfo =
|
||||
let f = fs: [ fs.mountPoint (if fs.device != null then fs.device else "/dev/disk/by-label/${fs.label}") fs.fsType (builtins.concatStringsSep "," fs.options) ];
|
||||
in pkgs.writeText "initrd-fsinfo" (concatStringsSep "\n" (concatMap f fileSystems));
|
||||
|
||||
setHostId = optionalString (config.networking.hostId != null) ''
|
||||
hi="${config.networking.hostId}"
|
||||
${if pkgs.stdenv.isBigEndian then ''
|
||||
echo -ne "\x''${hi:0:2}\x''${hi:2:2}\x''${hi:4:2}\x''${hi:6:2}" > /etc/hostid
|
||||
'' else ''
|
||||
echo -ne "\x''${hi:6:2}\x''${hi:4:2}\x''${hi:2:2}\x''${hi:0:2}" > /etc/hostid
|
||||
''}
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
# The closure of the init script of boot stage 1 is what we put in
|
||||
# the initial RAM disk.
|
||||
initialRamdisk = pkgs.makeInitrd {
|
||||
name = "initrd-${kernel-name}";
|
||||
inherit (config.boot.initrd) compressor compressorArgs prepend;
|
||||
|
||||
contents =
|
||||
[ { object = bootStage1;
|
||||
symlink = "/init";
|
||||
}
|
||||
{ object = pkgs.writeText "mdadm.conf" config.boot.initrd.services.swraid.mdadmConf;
|
||||
symlink = "/etc/mdadm.conf";
|
||||
}
|
||||
{ object = pkgs.runCommand "initrd-kmod-blacklist-ubuntu" {
|
||||
src = "${pkgs.kmod-blacklist-ubuntu}/modprobe.conf";
|
||||
preferLocalBuild = true;
|
||||
} ''
|
||||
target=$out
|
||||
${pkgs.buildPackages.perl}/bin/perl -0pe 's/## file: iwlwifi.conf(.+?)##/##/s;' $src > $out
|
||||
'';
|
||||
symlink = "/etc/modprobe.d/ubuntu.conf";
|
||||
}
|
||||
{ object = config.environment.etc."modprobe.d/nixos.conf".source;
|
||||
symlink = "/etc/modprobe.d/nixos.conf";
|
||||
}
|
||||
{ object = pkgs.kmod-debian-aliases;
|
||||
symlink = "/etc/modprobe.d/debian.conf";
|
||||
}
|
||||
] ++ lib.optionals config.services.multipath.enable [
|
||||
{ object = pkgs.runCommand "multipath.conf" {
|
||||
src = config.environment.etc."multipath.conf".text;
|
||||
preferLocalBuild = true;
|
||||
} ''
|
||||
target=$out
|
||||
printf "$src" > $out
|
||||
substituteInPlace $out \
|
||||
--replace ${config.services.multipath.package}/lib ${extraUtils}/lib
|
||||
'';
|
||||
symlink = "/etc/multipath.conf";
|
||||
}
|
||||
] ++ (lib.mapAttrsToList
|
||||
(symlink: options:
|
||||
{
|
||||
inherit symlink;
|
||||
object = options.source;
|
||||
}
|
||||
)
|
||||
config.boot.initrd.extraFiles);
|
||||
};
|
||||
|
||||
# Script to add secret files to the initrd at bootloader update time
|
||||
initialRamdiskSecretAppender =
|
||||
let
|
||||
compressorExe = initialRamdisk.compressorExecutableFunction pkgs;
|
||||
in pkgs.writeScriptBin "append-initrd-secrets"
|
||||
''
|
||||
#!${pkgs.bash}/bin/bash -e
|
||||
function usage {
|
||||
echo "USAGE: $0 INITRD_FILE" >&2
|
||||
echo "Appends this configuration's secrets to INITRD_FILE" >&2
|
||||
}
|
||||
|
||||
if [ $# -ne 1 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1"x = "--helpx" ]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
${lib.optionalString (config.boot.initrd.secrets == {})
|
||||
"exit 0"}
|
||||
|
||||
export PATH=${pkgs.coreutils}/bin:${pkgs.libarchive}/bin:${pkgs.gzip}/bin:${pkgs.findutils}/bin
|
||||
|
||||
function cleanup {
|
||||
if [ -n "$tmp" -a -d "$tmp" ]; then
|
||||
rm -fR "$tmp"
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
tmp=$(mktemp -d ''${TMPDIR:-/tmp}/initrd-secrets.XXXXXXXXXX)
|
||||
|
||||
${lib.concatStringsSep "\n" (mapAttrsToList (dest: source:
|
||||
let source' = if source == null then dest else toString source; in
|
||||
''
|
||||
mkdir -p $(dirname "$tmp/.initrd-secrets/${dest}")
|
||||
cp -a ${source'} "$tmp/.initrd-secrets/${dest}"
|
||||
''
|
||||
) config.boot.initrd.secrets)
|
||||
}
|
||||
|
||||
(cd "$tmp" && find . -print0 | sort -z | bsdtar --uid 0 --gid 0 -cnf - -T - | bsdtar --null -cf - --format=newc @-) | \
|
||||
${compressorExe} ${lib.escapeShellArgs initialRamdisk.compressorArgs} >> "$1"
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
config = mkIf config.boot.initrd.enable {
|
||||
|
||||
system.build = lib.mapAttrs (_: lib.mkForce) { inherit bootStage1 initialRamdisk initialRamdiskSecretAppender extraUtils; };
|
||||
|
||||
};
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
#! @shell@
|
||||
|
||||
systemConfig=@systemConfig@
|
||||
|
||||
export HOME=/root PATH="@path@"
|
||||
|
||||
|
||||
if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" != true ]; then
|
||||
# Process the kernel command line.
|
||||
for o in $(</proc/cmdline); do
|
||||
case $o in
|
||||
boot.debugtrace)
|
||||
# Show each command.
|
||||
set -x
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
||||
# Print a greeting.
|
||||
echo
|
||||
echo -e "\e[1;32m<<< NixOS Stage 2 >>>\e[0m"
|
||||
echo
|
||||
|
||||
|
||||
# Normally, stage 1 mounts the root filesystem read/writable.
|
||||
# However, in some environments, stage 2 is executed directly, and the
|
||||
# root is read-only. So make it writable here.
|
||||
if [ -z "$container" ]; then
|
||||
mount -n -o remount,rw none /
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# Likewise, stage 1 mounts /proc, /dev and /sys, so if we don't have a
|
||||
# stage 1, we need to do that here.
|
||||
if [ ! -e /proc/1 ]; then
|
||||
specialMount() {
|
||||
local device="$1"
|
||||
local mountPoint="$2"
|
||||
local options="$3"
|
||||
local fsType="$4"
|
||||
|
||||
# We must not overwrite this mount because it's bind-mounted
|
||||
# from stage 1's /run
|
||||
if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" = true ] && [ "${mountPoint}" = /run ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
install -m 0755 -d "$mountPoint"
|
||||
mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
|
||||
}
|
||||
source @earlyMountScript@
|
||||
fi
|
||||
|
||||
|
||||
if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" = true ]; then
|
||||
echo "booting system configuration ${systemConfig}"
|
||||
else
|
||||
echo "booting system configuration $systemConfig" > /dev/kmsg
|
||||
fi
|
||||
|
||||
|
||||
# Make /nix/store a read-only bind mount to enforce immutability of
|
||||
# the Nix store. Note that we can't use "chown root:nixbld" here
|
||||
# because users/groups might not exist yet.
|
||||
# Silence chown/chmod to fail gracefully on a readonly filesystem
|
||||
# like squashfs.
|
||||
chown -f 0:30000 /nix/store
|
||||
chmod -f 1775 /nix/store
|
||||
if [ -n "@readOnlyStore@" ]; then
|
||||
if ! [[ "$(findmnt --noheadings --output OPTIONS /nix/store)" =~ ro(,|$) ]]; then
|
||||
if [ -z "$container" ]; then
|
||||
mount --bind /nix/store /nix/store
|
||||
else
|
||||
mount --rbind /nix/store /nix/store
|
||||
fi
|
||||
mount -o remount,ro,bind /nix/store
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Log the script output to /dev/kmsg or /run/log/stage-2-init.log.
|
||||
# Only at this point are all the necessary prerequisites ready for these commands.
|
||||
exec {logOutFd}>&1 {logErrFd}>&2
|
||||
if test -w /dev/kmsg; then
|
||||
exec > >(tee -i /proc/self/fd/"$logOutFd" | while read -r line; do
|
||||
if test -n "$line"; then
|
||||
echo "<7>stage-2-init: $line" > /dev/kmsg
|
||||
fi
|
||||
done) 2>&1
|
||||
else
|
||||
mkdir -p /run/log
|
||||
exec > >(tee -i /run/log/stage-2-init.log) 2>&1
|
||||
fi
|
||||
|
||||
|
||||
# Required by the activation script
|
||||
install -m 0755 -d /etc /etc/nixos
|
||||
install -m 01777 -d /tmp
|
||||
|
||||
|
||||
# Run the script that performs all configuration activation that does
|
||||
# not have to be done at boot time.
|
||||
echo "running activation script..."
|
||||
$systemConfig/activate
|
||||
|
||||
|
||||
# Record the boot configuration.
|
||||
ln -sfn "$systemConfig" /run/booted-system
|
||||
|
||||
# copy eudev rules over to /var
|
||||
cp -ru @eudev@/var/lib/udev /var/lib/
|
||||
|
||||
# Run any user-specified commands.
|
||||
@shell@ @postBootCommands@
|
||||
|
||||
|
||||
# Reset the logging file descriptors.
|
||||
exec 1>&$logOutFd 2>&$logErrFd
|
||||
exec {logOutFd}>&- {logErrFd}>&-
|
||||
|
||||
|
||||
mkdir -p \
|
||||
/run/etc/syndicate/core \
|
||||
/run/etc/syndicate/services
|
||||
|
||||
# Start Synit.
|
||||
echo "starting Synit..."
|
||||
exec synit-pid1
|
|
@ -0,0 +1,27 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
config = {
|
||||
|
||||
system.build.bootStage2 = lib.mkForce (pkgs.substituteAll {
|
||||
src = ./stage-2-init.sh;
|
||||
shellDebug = "${pkgs.bashInteractive}/bin/bash";
|
||||
shell = "${pkgs.bash}/bin/bash";
|
||||
isExecutable = true;
|
||||
inherit (config.nix) readOnlyStore;
|
||||
inherit (config.system.build) earlyMountScript;
|
||||
path = lib.makeBinPath [
|
||||
pkgs.coreutils
|
||||
pkgs.utillinux
|
||||
pkgs.synit-pid1
|
||||
];
|
||||
inherit (pkgs) eudev;
|
||||
postBootCommands = pkgs.writeText "local-cmds" ''
|
||||
${config.boot.postBootCommands}
|
||||
${config.powerManagement.powerUpCommands}
|
||||
'';
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<require-service <config-watcher "/run/etc/syndicate/services" $.>>
|
|
@ -0,0 +1,51 @@
|
|||
<require-service <daemon interface-monitor>>
|
||||
|
||||
<require-service <milestone network>>
|
||||
<depends-on <milestone network> <service-state <daemon interface-monitor> ready>>
|
||||
|
||||
<configure-interface "lo" <static "127.0.0.1/8">>
|
||||
|
||||
? <configure-interface ?ifname <static ?ipaddr>> [
|
||||
! <exec ["@ip@" "address" "add" "dev" $ifname $ipaddr]>
|
||||
?- ! <exec ["@ip@" "address" "del" "dev" $ifname $ipaddr] never>
|
||||
]
|
||||
|
||||
? <configure-interface ?ifname <dhcp>> [
|
||||
<require-service <daemon <udhcpc $ifname>>>
|
||||
]
|
||||
|
||||
? <run-service <daemon <udhcpc ?ifname>>> [
|
||||
<daemon <udhcpc $ifname> ["@udhcpc@" "-i" $ifname "-fR"]>
|
||||
]
|
||||
|
||||
<daemon interface-monitor {
|
||||
argv: "@interfaceMonitor@"
|
||||
protocol: application/syndicate
|
||||
}>
|
||||
|
||||
? <machine-dataspace ?machine> [
|
||||
? <service-object <daemon interface-monitor> ?cap> [
|
||||
$cap {
|
||||
machine: $machine
|
||||
}
|
||||
]
|
||||
|
||||
$machine ? <interface ?ifname _ _ _ _ _ _> [
|
||||
$log ! <log "-" { saw-machine-interface: $ifname }>
|
||||
$config [
|
||||
! <exec ["@ip@" "link" "set" $ifname "up"]>
|
||||
?- ! <exec ["@ip@" "link" "set" $ifname "down"] never>
|
||||
]
|
||||
]
|
||||
|
||||
$machine ? <interface ?ifname _ normal up up carrier _> [
|
||||
$config <configure-interface $ifname <dhcp>>
|
||||
]
|
||||
$machine ? <interface ?ifname _ normal up unknown carrier _> [
|
||||
$config <configure-interface $ifname <dhcp>>
|
||||
]
|
||||
|
||||
$machine ? <route ?addressFamily default _ _ _ _> [
|
||||
$config <default-route $addressFamily>
|
||||
]
|
||||
]
|
|
@ -0,0 +1,3 @@
|
|||
<require-service <daemon ntpd>>
|
||||
<depends-on <daemon ntpd> <default-route ipv4>>
|
||||
<daemon ntpd "@ntpd@ -d -n -p pool.ntp.org">
|
|
@ -0,0 +1,5 @@
|
|||
<require-service <daemon sshd>>
|
||||
<depends-on <daemon sshd> <service-state <milestone network> up>>
|
||||
<depends-on <daemon sshd> <service-state <daemon ssh-host-keys> complete>>
|
||||
<daemon sshd "@sshd@ -D -f /etc/ssh/sshd_config">
|
||||
<daemon ssh-host-keys <one-shot "@ssh-keygen@ -A">>
|
|
@ -0,0 +1,20 @@
|
|||
let ?settingsDir = "/etc/syndicate/user-settings"
|
||||
|
||||
let ?settings = <* $config [
|
||||
<rewrite ?item <user-setting $item>>
|
||||
]>
|
||||
|
||||
<require-service <config-watcher $settingsDir { config: $settings }>>
|
||||
|
||||
<require-service <daemon user-settings-daemon>>
|
||||
<daemon user-settings-daemon {
|
||||
argv: "@user-settings-daemon@"
|
||||
protocol: application/syndicate
|
||||
}>
|
||||
|
||||
? <service-object <daemon user-settings-daemon> ?cap> [
|
||||
$cap {
|
||||
config: $config
|
||||
settingsDir: $settingsDir
|
||||
}
|
||||
]
|
|
@ -0,0 +1,177 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
config = {
|
||||
|
||||
boot.initrd = {
|
||||
enable = true;
|
||||
network.enable = false;
|
||||
systemd.enable = false;
|
||||
verbose = true;
|
||||
};
|
||||
|
||||
environment.etc = {
|
||||
|
||||
"syndicate/boot/001-console-getty.pr".text = ''
|
||||
<require-service <daemon console-getty>>
|
||||
<daemon console-getty [
|
||||
"${lib.getBin pkgs.util-linux}/bin/agetty"
|
||||
"--login-program"
|
||||
"${config.services.getty.loginProgram}"
|
||||
"--noclear"
|
||||
"--keep-baud"
|
||||
"console"
|
||||
"115200,38400,9600"
|
||||
"linux"
|
||||
]>
|
||||
'';
|
||||
|
||||
"syndicate/boot/020-load-core-layer.pr".text = ''
|
||||
; Attenuate `$config` by rewriting plain `require-service` assertions to `require-core-service`
|
||||
; assertions. Allow all other assertions through.
|
||||
;
|
||||
let ?sys = <* $config [
|
||||
<rewrite <require-service ?s> <require-core-service $s>>
|
||||
<filter _>
|
||||
]>
|
||||
|
||||
; Give meaning to `require-core-service`: it is an ordinary `require-service`, plus a
|
||||
; declaration that the `core` milestone depends on the service.
|
||||
;
|
||||
? <require-core-service ?s> [
|
||||
<depends-on <milestone core> <service-state $s up>>
|
||||
<require-service $s>
|
||||
]
|
||||
|
||||
; Load config in the `core` directory, using the wrapped `config` so that all plain services
|
||||
; required are changed to be *core* services.
|
||||
;
|
||||
<require-service <config-watcher "/run/current-system/etc/syndicate/core" {
|
||||
config: $sys
|
||||
gatekeeper: $gatekeeper
|
||||
log: $log
|
||||
}>>
|
||||
|
||||
; In addition, require the `core` milestone explicitly.
|
||||
;
|
||||
<require-service <milestone core>>
|
||||
'';
|
||||
|
||||
"syndicate/boot/030-load-services.pr".text = ''
|
||||
; Attenuate `$config` by rewriting plain `require-service` assertions to
|
||||
; `require-basic-service` assertions. Allow all other assertions through.
|
||||
;
|
||||
let ?basic = <* $config [
|
||||
<rewrite <require-service ?s> <require-basic-service $s>>
|
||||
<filter _>
|
||||
]>
|
||||
|
||||
; Give meaning to `require-basic-service`: it is an ordinary `require-service`, plus a
|
||||
; declaration that the service depends on the `core` milestone.
|
||||
;
|
||||
? <require-basic-service ?s> [
|
||||
<depends-on $s <service-state <milestone core> up>>
|
||||
<require-service $s>
|
||||
]
|
||||
|
||||
; Once we see that the `core` milestone is ready, start processing the `services`
|
||||
; directory.
|
||||
;
|
||||
? <service-state <milestone core> up> [
|
||||
<require-service <config-watcher "/run/current-system/etc/syndicate/services" {
|
||||
config: $basic
|
||||
gatekeeper: $gatekeeper
|
||||
log: $log
|
||||
}>>
|
||||
]
|
||||
'';
|
||||
|
||||
"syndicate/core/configdirs.pr".text = ''
|
||||
<require-service <config-watcher "/run/etc/syndicate/core" $.>>
|
||||
<require-service <config-watcher "/etc/syndicate/core" $.>>
|
||||
'';
|
||||
|
||||
"syndicate/core/hostname.pr".text = ''
|
||||
<require-service <daemon hostname>>
|
||||
<daemon hostname <one-shot ["${pkgs.nettools}/bin/hostname" "${config.networking.hostName}"]>>
|
||||
'';
|
||||
|
||||
"syndicate/core/eudev.pr".text = let
|
||||
initialScanScript = pkgs.writeScript "eudev-initial-scan.sh" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
set -e
|
||||
export PATH=${lib.makeBinPath [ pkgs.eudev ]}
|
||||
echo "" > /proc/sys/kernel/hotplug
|
||||
udevadm trigger --type=subsystems --action=add
|
||||
udevadm trigger --type=devices --action=add
|
||||
udevadm settle --timeout=30
|
||||
'';
|
||||
in ''
|
||||
<require-service <daemon eudev>>
|
||||
<daemon eudev ["${pkgs.eudev}/bin/udevd" "--children-max=5"]>
|
||||
|
||||
<require-service <daemon eudev-initial-scan>>
|
||||
<depends-on <daemon eudev-initial-scan> <service-state <daemon eudev> up>>
|
||||
<daemon eudev-initial-scan <one-shot ${initialScanScript}>>
|
||||
'';
|
||||
|
||||
"syndicate/core/machine-dataspace.pr".text = ''
|
||||
let ?ds = dataspace
|
||||
<machine-dataspace $ds>
|
||||
|
||||
$ds ? ?r [
|
||||
$log ! <log "-" { line: "machine" |+++|: $r }>
|
||||
?- $log ! <log "-" { line: "machine" |---|: $r }>
|
||||
]
|
||||
'';
|
||||
|
||||
"syndicate/services/configdirs.pr".source =
|
||||
./syndicate/services/configdirs.pr;
|
||||
|
||||
"syndicate/services/network.pr".source = pkgs.substituteAll {
|
||||
src = ./syndicate/services/network.pr;
|
||||
interfaceMonitor =
|
||||
"${pkgs.python3Packages.synit-daemons}/bin/interface-monitor";
|
||||
ip = "${pkgs.iproute2}/bin/ip";
|
||||
udhcpc = "${pkgs.busybox}/bin/udhcpc";
|
||||
};
|
||||
|
||||
"syndicate/services/ntpd.pr".source = pkgs.substituteAll {
|
||||
src = ./syndicate/services/ntpd.pr;
|
||||
ntpd = "${pkgs.busybox}/bin/ntpd";
|
||||
};
|
||||
|
||||
"syndicate/services/sshd.pr".source = pkgs.substituteAll {
|
||||
src = ./syndicate/services/sshd.pr;
|
||||
sshd = "${pkgs.openssh}/bin/sshd";
|
||||
ssh-keygen = "${pkgs.openssh}/bin/ssh-keygen";
|
||||
};
|
||||
|
||||
"syndicate/services/userSettings.pr".source = pkgs.substituteAll {
|
||||
src = ./syndicate/services/userSettings.pr;
|
||||
user-settings-daemon =
|
||||
"${pkgs.python3Packages.synit-daemons}/bin/user-settings-daemon";
|
||||
};
|
||||
|
||||
} // (builtins.listToAttrs (map (file: {
|
||||
name = "syndicate/boot/${file}";
|
||||
value.source =
|
||||
"${pkgs.synit-pid1.src}/packaging/packages/synit-config/files/etc/syndicate/boot/${file}";
|
||||
}) [ "010-exec.pr" "010-milestone.pr" "010-service-state-up.pr" ]));
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
synit-pid1
|
||||
syndicate-server
|
||||
(writeScriptBin "synit-log" ''
|
||||
#! ${lib.getBin bash}/bin/bash
|
||||
${lib.getBin coreutils}/bin/mkdir -p /var/log/synit
|
||||
exec ${lib.getBin s6}/bin/s6-log t /var/log/synit
|
||||
'')
|
||||
];
|
||||
|
||||
systemd.package = pkgs.systemd // { meta.broken = true; };
|
||||
|
||||
};
|
||||
}
|
|
@ -2,101 +2,118 @@
|
|||
with lib;
|
||||
|
||||
{
|
||||
options.services.syndicate-server = {
|
||||
enable = mkEnableOption "the Syndicate dataspace server";
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "wheel";
|
||||
example = "users";
|
||||
description = "Group account under which the Syndicate server runs.";
|
||||
options.services.syndicate = mkOption {
|
||||
default = { };
|
||||
example = {
|
||||
tty1 = {
|
||||
enable = true;
|
||||
user = "jane";
|
||||
config = [ "/etc/syndicate" ];
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
Syndicate dataspace server instances.
|
||||
If the key is in the form of "tty''${N}" it will
|
||||
be attached to the appropriate teletypewriter.
|
||||
'';
|
||||
type = types.attrsOf (types.submodule {
|
||||
options = {
|
||||
enable = mkEnableOption "this Syndicate dataspace server instance";
|
||||
|
||||
package = mkOption {
|
||||
default = pkgs.syndicate-rs;
|
||||
defaultText = "pkgs.syndicate-rs";
|
||||
type = types.package;
|
||||
description = "The package to use for the Syndicate dataspace server.";
|
||||
};
|
||||
runInDbusSession = mkEnableOption "dbus-run-session wrapper";
|
||||
|
||||
tcpListeners = mkOption {
|
||||
default = [ ];
|
||||
example = [{
|
||||
address = "0.0.0.0";
|
||||
port = 8001;
|
||||
}];
|
||||
type = with types;
|
||||
listOf (submodule {
|
||||
options = {
|
||||
address = mkOption { type = str; };
|
||||
port = mkOption { type = port; };
|
||||
};
|
||||
});
|
||||
description = "TCP ports to listen for connections on.";
|
||||
};
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
example = "jane";
|
||||
description = "User account under which the Syndicate server runs.";
|
||||
};
|
||||
|
||||
unixListeners = mkOption {
|
||||
default = [ "/run/syndicate/ds" ];
|
||||
type = types.listOf types.path;
|
||||
description = "Sockets to listen for connections on.";
|
||||
};
|
||||
package = mkOption {
|
||||
default = pkgs.syndicate-server;
|
||||
defaultText = "pkgs.syndicate-server";
|
||||
type = types.package;
|
||||
description =
|
||||
"The package to use for the Syndicate dataspace server.";
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
type = types.listOf types.path;
|
||||
description = "Configurations to load.";
|
||||
example = [ "/etc/syndicate" ];
|
||||
};
|
||||
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
systemd.services = let
|
||||
serverCfgs =
|
||||
lib.attrsets.filterAttrs (_: cfg: cfg.enable) config.services.syndicate;
|
||||
in builtins.listToAttrs (lib.lists.flatten (lib.attrsets.mapAttrsToList
|
||||
(name: cfg:
|
||||
let
|
||||
configFileName = "syndicate-nixos-config.pr";
|
||||
runtimeConfig = "\${RUNTIME_DIRECTORY}/${configFileName}";
|
||||
configFile = pkgs.writeText configFileName
|
||||
(lib.strings.concatMapStrings (dir: ''
|
||||
<require-service <config-watcher "${dir}" $.>>
|
||||
'') cfg.config);
|
||||
in [{
|
||||
name = "syndicate-${name}";
|
||||
value = let
|
||||
serviceConfig = let
|
||||
loadConfig =
|
||||
"${pkgs.coreutils}/bin/cp ${configFile} ${runtimeConfig}";
|
||||
in {
|
||||
RuntimeDirectory = name;
|
||||
ExecStartPre = loadConfig;
|
||||
ExecStart = "${
|
||||
lib.optionalString cfg.runInDbusSession
|
||||
"${pkgs.dbus}/bin/dbus-run-session "
|
||||
}${cfg.package}/bin/syndicate-server --no-banner --config ${runtimeConfig}";
|
||||
ExecReload = loadConfig;
|
||||
User = cfg.user;
|
||||
};
|
||||
in {
|
||||
description = "Syndicate dataspace server";
|
||||
restartIfChanged = false;
|
||||
reloadTriggers = [ configFile ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
} // (if builtins.match "tty[0-9]" name == null then {
|
||||
inherit serviceConfig;
|
||||
} else {
|
||||
after = [
|
||||
"systemd-user-sessions.service"
|
||||
"systemd-logind.service"
|
||||
"getty@${name}.service"
|
||||
];
|
||||
wants = [ "dbus.socket" "systemd-logind.service" ];
|
||||
conflicts = [ "getty@${name}.service" ];
|
||||
unitConfig.ConditionPathExists = "/dev/${name}";
|
||||
serviceConfig = serviceConfig // {
|
||||
PAMName = "login";
|
||||
StandardError = "journal";
|
||||
StandardInput = "tty-fail";
|
||||
StandardOutput = "journal";
|
||||
TTYPath = "/dev/${name}";
|
||||
TTYReset = "yes";
|
||||
TTYVHangup = "yes";
|
||||
TTYVTDisallocate = "yes";
|
||||
UtmpIdentifier = "%n";
|
||||
UtmpMode = "user";
|
||||
WorkingDirectory = "~";
|
||||
};
|
||||
});
|
||||
}]) (lib.attrsets.filterAttrs (_: cfg: cfg.enable)
|
||||
config.services.syndicate)));
|
||||
|
||||
systemd.targets.multi-user.wants = lib.lists.flatten
|
||||
(lib.attrsets.mapAttrsToList
|
||||
(name: cfg: lib.optional cfg.enable "syndicate-${name}.service")
|
||||
config.services.syndicate);
|
||||
|
||||
};
|
||||
|
||||
config = let
|
||||
cfg = config.services.syndicate-server;
|
||||
configDir = "/run/syndicate/config";
|
||||
requireServiceRelayListener = spec:
|
||||
"<require-service <relay-listener ${spec}>>";
|
||||
in mkIf cfg.enable {
|
||||
|
||||
systemd.services.syndicate-server = {
|
||||
description = "Syndicate dataspace server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p ${configDir}";
|
||||
ExecStart = "${cfg.package}/bin/syndicate-server --config ${configDir}";
|
||||
Group = cfg.group;
|
||||
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
|
||||
DynamicUser = true;
|
||||
Restart = "always";
|
||||
RuntimeDirectory = "syndicate";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.syndicate-server-unix-listeners = {
|
||||
description = "Configure Syndicate unix listeners";
|
||||
after = [ "syndicate-server.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = let
|
||||
prsFile = builtins.toFile "unix-listeners.pr"
|
||||
(lib.strings.concatMapStrings
|
||||
(path: requireServiceRelayListener ''<unix "${path}">'')
|
||||
cfg.unixListeners);
|
||||
in "${pkgs.coreutils}/bin/cp ${prsFile} ${configDir}/nixos-unix-listeners.pr";
|
||||
ExecStop =
|
||||
"${pkgs.coreutils}/bin/rm ${configDir}/nixos-unix-listeners.pr";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.syndicate-server-tcp-listeners = {
|
||||
description = "Configure Syndicate TCP listeners";
|
||||
after = [ "syndicate-server.service" "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = let
|
||||
prsFile = builtins.toFile "tcp-listeners.pr"
|
||||
(lib.strings.concatMapStrings ({ address, port }:
|
||||
requireServiceRelayListener
|
||||
''<tcp "${address}" ${toString port}>'') cfg.tcpListeners);
|
||||
in "${pkgs.coreutils}/bin/cp ${prsFile} ${configDir}/nixos-tcp-listeners.pr";
|
||||
ExecStop =
|
||||
"${pkgs.coreutils}/bin/rm ${configDir}/nixos-tcp-listeners.pr";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
{ lib, stdenv, buildNimPackage, fetchFromGitea, fetchFromGitHub, runCommand
|
||||
, nim-unwrapped, preserves }:
|
||||
|
||||
let
|
||||
compiler = runCommand "compiler.nimble" { inherit (nim-unwrapped) src; } ''
|
||||
mkdir -p $out
|
||||
tar xf $src --strip-components=1 -C $out
|
||||
'';
|
||||
|
||||
npeg = fetchFromGitHub {
|
||||
owner = "zevv";
|
||||
repo = "npeg";
|
||||
rev = "0.25.0";
|
||||
hash = "sha256-E/0hCz0XsoAb/bAksqrKTyi8/FwBdP8kT6uUUAdru68=";
|
||||
};
|
||||
|
||||
in buildNimPackage rec {
|
||||
pname = "preserves";
|
||||
version = "20220625";
|
||||
src = fetchFromGitea {
|
||||
domain = "git.syndicate-lang.org";
|
||||
owner = "ehmry";
|
||||
repo = "${pname}-nim";
|
||||
rev = version;
|
||||
sha256 = "sha256-ZNgBlIOKyWD0R5wZvGb/0K5tUpz5q5QpET4Qa/kxhkA=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ compiler npeg ];
|
||||
propagatedNativeBuildInputs =
|
||||
lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) preserves;
|
||||
# propagate the utilities of this package for this build platform
|
||||
preConfigure = "substituteInPlace preserves.nimble --replace '# bin ' 'bin '";
|
||||
|
||||
postInstall = ''
|
||||
pushd $out/bin
|
||||
for link in preserves_decode preserves_from_json preserves_to_json;
|
||||
do ln -s preserves_encode $link
|
||||
done
|
||||
popd
|
||||
'';
|
||||
doCheck = true;
|
||||
|
||||
meta = src.meta // {
|
||||
maintainers = [ lib.maintainers.ehmry ];
|
||||
license = lib.licenses.unlicense;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{ lib, buildPythonPackage, fetchFromGitea, python, setuptools-scm }:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "preserves";
|
||||
version = "unstable-2022-03-08";
|
||||
|
||||
src = fetchFromGitea {
|
||||
domain = "git.syndicate-lang.org";
|
||||
owner = "syndicate-lang";
|
||||
repo = pname;
|
||||
rev = "197359ff22fa701d8b497860e8eb84dba209e00e";
|
||||
sha256 = "sha256-1nlyqcNIDGuNzo5/ObjF4YIWbpD8lxgVFXcKM+Dv6PY=";
|
||||
};
|
||||
|
||||
sourceRoot = "source/implementations/python";
|
||||
|
||||
buildInputs = [ setuptools-scm ];
|
||||
|
||||
postInstall =
|
||||
"install -t $out/lib/${python.libPrefix}/site-packages/preserves preserves/*.prb ";
|
||||
|
||||
meta = src.meta // {
|
||||
homepage = "https://syndicate-lang.org";
|
||||
maintainers = with lib.maintainers; [ ehmry ];
|
||||
};
|
||||
}
|
|
@ -5,13 +5,13 @@ rustPlatform.buildRustPackage rec {
|
|||
# use the name of the actual utility so that
|
||||
# nix run …#preserves-tools works as expected.
|
||||
|
||||
version = "1.0.0";
|
||||
version = "2.3.0";
|
||||
src = fetchCrate {
|
||||
pname = "preserves-tools"; # name of the crate
|
||||
inherit version;
|
||||
sha256 = "10vy7pmdbxkcwbr1qwqqv1lfi622pk8ncbp1hn5jrddxrv92q4ph";
|
||||
sha256 = "sha256-I9dqY2pej/HRQg2VGkEoWKOlo4c9TYwk/jw23eN1nlU=";
|
||||
};
|
||||
cargoHash = "sha256-h6ulvjTDTj8/fmzEn1YgZKmze4jwpmGjcSq78hmq2cU=";
|
||||
cargoHash = "sha256-0UMGDoyfdEJQQDoUadbU6Ev6yA2k0sQHRvO/Z+4QF5g=";
|
||||
nativeBuildInputs = [ rust ];
|
||||
|
||||
meta = {
|
|
@ -0,0 +1,75 @@
|
|||
{ lib, stdenv, fetchurl, autoPatchelfHook, makeWrapper, unzip, alsa-lib, libGL
|
||||
, libpulseaudio, libuuid, nas, openssl, pango, sndio, xorg }:
|
||||
|
||||
let
|
||||
versionA = "6.0";
|
||||
versionB = "22101";
|
||||
versionC = "202206021410";
|
||||
bits = with stdenv.hostPlatform;
|
||||
if is32bit then
|
||||
"32"
|
||||
else if is64bit then
|
||||
"64"
|
||||
else
|
||||
throw "too many addressing bits";
|
||||
sources = {
|
||||
i686-linux = fetchurl {
|
||||
url =
|
||||
"http://files.squeak.org/${versionA}/Squeak${versionA}-${versionB}-32bit/Squeak${versionA}-${versionB}-${bits}bit-${versionC}-Linux-x86.tar.gz";
|
||||
sha256 = "sha256-z7o3R/KwqfYPMtjk93aCNrM2tHt+pDmYSLn3Sd53hVg=";
|
||||
};
|
||||
x86_64-linux = fetchurl {
|
||||
url =
|
||||
"http://files.squeak.org/${versionA}/Squeak${versionA}-${versionB}-${bits}bit/Squeak${versionA}-${versionB}-${bits}bit-${versionC}-Linux-x64.tar.gz";
|
||||
sha256 = "sha256-+HnISzA2LxgJTvAjXrpP6/jmo3w0ABzJdy3pPWceIcg=";
|
||||
};
|
||||
};
|
||||
in stdenv.mkDerivation rec {
|
||||
pname = "squeak";
|
||||
version = "${versionA}-${versionB}-${versionC}";
|
||||
|
||||
src = sources.${stdenv.system};
|
||||
|
||||
nativeBuildInputs = [ autoPatchelfHook makeWrapper unzip ];
|
||||
|
||||
buildInputs = with xorg; [
|
||||
alsa-lib
|
||||
libGL
|
||||
libICE
|
||||
libSM
|
||||
libX11
|
||||
libXext
|
||||
libXrender
|
||||
libpulseaudio
|
||||
libuuid
|
||||
nas
|
||||
pango
|
||||
sndio
|
||||
];
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp -a bin $out/lib
|
||||
cp -a shared/* $out/lib
|
||||
makeWrapper $out/lib/squeak $out/bin/squeak \
|
||||
--prefix LD_LIBRARY_PATH ":" "$out/lib:${
|
||||
lib.makeLibraryPath [ openssl ]
|
||||
}" \
|
||||
--set SQUEAK_IMAGE $out/lib/Squeak${versionA}-${versionB}-${bits}bit.image
|
||||
'';
|
||||
|
||||
preFixup = ''
|
||||
patchelf $out/lib/vm-sound-sndio.so \
|
||||
--replace-needed libsndio.so.6.1 libsndio.so
|
||||
'';
|
||||
meta = {
|
||||
broken = !(builtins.hasAttr stdenv.system sources);
|
||||
description = "Squeak virtual machine and image";
|
||||
homepage = "https://squeak.org/";
|
||||
license = with lib.licenses; [ asl20 mit ];
|
||||
maintainers = with lib.maintainers; [ ehmry ];
|
||||
platforms = builtins.attrNames sources;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
{ lib, buildPythonApplication, fetchFromGitHub }:
|
||||
|
||||
buildPythonApplication rec {
|
||||
pname = "squeaker";
|
||||
version = "unstable-2022-03-04";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "tonyg";
|
||||
repo = pname;
|
||||
rev = "caf2ef0b6d5c3cd211b966d3933d4baa885676b5";
|
||||
hash = "sha256-DXYKT3buaQ0WfebNwdGT3s2eAAKpndmZ3TczCD/alH0=";
|
||||
};
|
||||
|
||||
# TODO: could inject squeak into the wrapper,
|
||||
# but for now let the environment pick the VM
|
||||
# propagatedBuildInputs = [ squeak ];
|
||||
|
||||
dontBuild = true;
|
||||
doCheck = false;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
install -Dt $out/bin squeaker
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = src.meta // {
|
||||
description = "Like Docker, but for Squeak";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ ehmry ];
|
||||
};
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{ lib, buildNimPackage, fetchFromGitea, fetchFromGitHub, preserves }:
|
||||
|
||||
let
|
||||
nimSHA2 = fetchFromGitHub {
|
||||
owner = "jangko";
|
||||
repo = "nimSHA2";
|
||||
rev = "b8f666069dff1ed0c5142dd1ca692f0e71434716";
|
||||
hash = "sha256-Wqb3mQ7638UOTze71mf6WMyGiw9qTwhbJiGGb+9OR2k=";
|
||||
};
|
||||
|
||||
in buildNimPackage rec {
|
||||
pname = "syndicate";
|
||||
version = "20220627";
|
||||
|
||||
src = fetchFromGitea {
|
||||
domain = "git.syndicate-lang.org";
|
||||
owner = "ehmry";
|
||||
repo = "${pname}-nim";
|
||||
rev = version;
|
||||
hash = "sha256-o9RvXLsGK1sJzA2eshAxxD2/PznIqmBrSTh8NmZdIJU=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ nimSHA2 preserves ];
|
||||
|
||||
meta = src.meta // {
|
||||
maintainers = [ lib.maintainers.ehmry ];
|
||||
license = lib.licenses.unlicense;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{ lib, buildPythonPackage, python, fetchFromGitea, setuptools-scm, preserves
|
||||
, websockets }:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "syndicate";
|
||||
version = "0.8.5";
|
||||
|
||||
src = fetchFromGitea {
|
||||
domain = "git.syndicate-lang.org";
|
||||
owner = "syndicate-lang";
|
||||
repo = "${pname}-py";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-OAvQxac06i8+R9zNWLjCtwOpVZ4t31q45ms6VuNyHGI=";
|
||||
};
|
||||
|
||||
buildInputs = [ setuptools-scm ];
|
||||
propagatedBuildInputs = [ preserves websockets ];
|
||||
|
||||
postInstall =
|
||||
"cp -rv syndicate/protocols $out/lib/${python.libPrefix}/site-packages/syndicate/";
|
||||
|
||||
meta = src.meta // {
|
||||
homepage = "https://syndicate-lang.org";
|
||||
description = "An implementation of Syndicated Actors for Python";
|
||||
maintainers = with lib.maintainers; [ ehmry ];
|
||||
};
|
||||
}
|
|
@ -1,20 +1,21 @@
|
|||
# https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/syndicate-server/APKBUILD
|
||||
|
||||
{ lib, rustPlatform, rust, fetchgit, pkg-config, openssl }:
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "syndicate-rs";
|
||||
version = "2021-09-01";
|
||||
pname = "syndicate-server";
|
||||
version = "0.24.0";
|
||||
src = fetchgit {
|
||||
url = "https://git.syndicate-lang.org/syndicate-lang/syndicate-rs.git";
|
||||
rev = "622115e13c69397dfa0beb433fdaf382949252b3";
|
||||
sha256 = "sha256-7XcCiDlUntLRB0MLYk+57RSe4f6NyqRa/Jc42xrPOnQ=";
|
||||
rev = "${pname}-v${version}";
|
||||
sha256 = "sha256-91dGi7CyI/6XkbpWbFtnb6XACIExHX/6XYVkKlkDTzc=";
|
||||
};
|
||||
cargoHash = "sha256-sagyE3yCmSNwqgZrgnw1ar7S37iZhVYYpn3WtIoBIU8=";
|
||||
cargoHash = "sha256-MXchqX8wvMwnT2Js0YVIgOKsZuGglnKRg3HsuyOgBsI=";
|
||||
nativeBuildInputs = [ rust pkg-config ];
|
||||
buildInputs = [ openssl ];
|
||||
|
||||
meta = {
|
||||
description =
|
||||
"Rust implementation of Dataspaces, Syndicate, and a high-speed networked dataspace broker.";
|
||||
description = "Syndicate broker server";
|
||||
homepage = "https://git.syndicate-lang.org/syndicate-lang/syndicate-rs/";
|
||||
maintainers = with lib.maintainers; [ ehmry ];
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
{ lib, buildNimPackage, fetchFromGitea, fetchFromGitHub, syndicate, libnotify }:
|
||||
|
||||
let
|
||||
gtk2 = fetchFromGitHub {
|
||||
owner = "nim-lang";
|
||||
repo = "gtk2";
|
||||
rev = "v1.3";
|
||||
hash = "sha256-KPHMF2gHIwjRuslJOhbf7KU0VUwp4Oe0+63YKKOBCPk=";
|
||||
};
|
||||
nim-libnotify = buildNimPackage rec {
|
||||
pname = "libnotify";
|
||||
version = "HEAD";
|
||||
src = fetchFromGitHub {
|
||||
owner = "FedericoCeratto";
|
||||
repo = "nim-${pname}";
|
||||
rev = "c715ca5b23377a9bceba93529339526fbca11517";
|
||||
hash = "sha256-Ifp7cV+Jxa7ZotggIkR6OT6I/f4LZ7ZBtSdfkjVtg7w=";
|
||||
};
|
||||
propagatedBuildInputs = [ libnotify gtk2 ];
|
||||
};
|
||||
in buildNimPackage rec {
|
||||
pname = "syndicate_utils";
|
||||
version = "20220628";
|
||||
|
||||
src = fetchFromGitea {
|
||||
domain = "git.syndicate-lang.org";
|
||||
owner = "ehmry";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
hash = "sha256-/HoPR/SFZzIzICvscse4s13EKvjXs6qr2puhkv5qBso=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ syndicate nim-libnotify ];
|
||||
nimFlags =
|
||||
[ "-p:${gtk2}/src/" ]; # everyone breaks the nimble rules, nim-lang included
|
||||
|
||||
meta = src.meta // {
|
||||
maintainers = [ lib.maintainers.ehmry ];
|
||||
license = lib.licenses.unlicense;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
{ lib, buildPythonApplication, python, pyroute2, syndicate, synit-pid1 }:
|
||||
|
||||
buildPythonApplication rec {
|
||||
pname = "interface-monitor";
|
||||
inherit (synit-pid1) version src;
|
||||
|
||||
propagatedBuildInputs = [ pyroute2 syndicate ];
|
||||
|
||||
format = "other";
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p \
|
||||
$out/bin \
|
||||
$out/lib/${python.libPrefix}/site-packages/synit/daemon \
|
||||
$out/protocols \
|
||||
|
||||
cp -r protocols/schema-bundle.bin $out/protocols
|
||||
pushd packaging/packages/synit-config/files/usr/lib/synit
|
||||
for f in *; do
|
||||
[ -f $f ] && cp $f $out/bin
|
||||
done
|
||||
pushd python/synit/daemon
|
||||
for f in *; do
|
||||
substitute $f $out/lib/${python.libPrefix}/site-packages/synit/daemon/$f \
|
||||
--replace "/home/tonyg/src/synit/protocols" "$out/protocols"
|
||||
done
|
||||
popd
|
||||
popd
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
# https://git.syndicate-lang.org/synit/synit/src/branch/main/packaging/packages/synit-pid1/APKBUILD
|
||||
|
||||
{ lib, rustPlatform, rust, fetchFromGitea }:
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "synit-pid1";
|
||||
version = "unstable-2022-07-25";
|
||||
src = fetchFromGitea {
|
||||
domain = "git.syndicate-lang.org";
|
||||
owner = "synit";
|
||||
repo = "synit";
|
||||
rev = "f91214d1b0c5de0ba6ef3debf39e2632adae9ec5";
|
||||
hash = "sha256-T+GzvanVTuHvazMQIPVxq02ANtVPM0yma43G3+UoI5c=";
|
||||
};
|
||||
|
||||
patchPhase =
|
||||
# Patch to take children and configuration from /run/booted-system.
|
||||
''
|
||||
runHook prePatch
|
||||
substituteInPlace src/main.rs \
|
||||
--replace '"/usr/bin/syndicate-server"' '"/run/booted-system/sw/bin/syndicate-server"' \
|
||||
--replace '"/sbin/synit-log"' '"/run/booted-system/sw/bin/synit-log"' \
|
||||
--replace '"/etc/syndicate/boot"' '"/run/booted-system/etc/syndicate/boot"' \
|
||||
|
||||
runHook postPatch
|
||||
'';
|
||||
|
||||
sourceRoot = "source/${pname}";
|
||||
cargoHash = "sha256-0py5bOFwCvZL1SBVx4bo0/jFvt8S5ef8AGGRHZFWsgQ=";
|
||||
nativeBuildInputs = [ rust ];
|
||||
|
||||
meta = {
|
||||
description = "Synit pid 1 program (patched for NixOS)";
|
||||
homepage = "https://synit.org/";
|
||||
maintainers = with lib.maintainers; [ ehmry ];
|
||||
};
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{ lib, buildNimPackage, fetchFromGitea, makeDesktopItem, syndicate }:
|
||||
|
||||
buildNimPackage rec {
|
||||
pname = "xdg_open_ng";
|
||||
version = "20220625";
|
||||
nimBinOnly = true;
|
||||
|
||||
src = fetchFromGitea {
|
||||
domain = "git.syndicate-lang.org";
|
||||
owner = "ehmry";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
hash = "sha256-yOuR4KYAMxlRc4AIr3ud0HzidHDQPeIiN3dzlnphLug=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ syndicate ];
|
||||
|
||||
desktopItem = makeDesktopItem rec {
|
||||
name = "xdg-open";
|
||||
desktopName = "Syndicate URI dispatcher (xdg-open)";
|
||||
exec = "${name} %U";
|
||||
mimeTypes = [
|
||||
"application/vnd.mozilla.xul+xml"
|
||||
"application/xhtml+xml"
|
||||
"text/html"
|
||||
"text/xml"
|
||||
"x-scheme-handler/http"
|
||||
"x-scheme-handler/https"
|
||||
];
|
||||
};
|
||||
|
||||
postInstall = ''
|
||||
mv $out/bin/xdg_open $out/bin/xdg-open
|
||||
cp -a $desktopItem/* $out/
|
||||
'';
|
||||
|
||||
meta = src.meta // {
|
||||
description = "Replacement for xdg-open that uses Syndicate for messaging.";
|
||||
maintainers = [ lib.maintainers.ehmry ];
|
||||
license = lib.licenses.unlicense;
|
||||
};
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
{ lib, nimPackages, fetchFromGitea, fetchFromGitHub }:
|
||||
with nimPackages;
|
||||
|
||||
let
|
||||
compiler = fetchFromGitHub {
|
||||
owner = "nim-lang";
|
||||
repo = "nim";
|
||||
rev = "v1.6.0";
|
||||
hash = "sha256-C9oveXIufv0HqMQw6eNmLbku4Sd7r28PKcRILvKYzn0=";
|
||||
};
|
||||
|
||||
npeg = fetchFromGitHub {
|
||||
owner = "zevv";
|
||||
repo = "npeg";
|
||||
rev = "0.25.0";
|
||||
hash = "sha256-E/0hCz0XsoAb/bAksqrKTyi8/FwBdP8kT6uUUAdru68=";
|
||||
};
|
||||
|
||||
in buildNimPackage rec {
|
||||
outputs = [ "out" "dev" ];
|
||||
|
||||
pname = "preserves";
|
||||
version = "3.0.0";
|
||||
src = fetchFromGitea {
|
||||
domain = "git.syndicate-lang.org";
|
||||
owner = "ehmry";
|
||||
repo = "preserves-nim";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-YcWJkDJIo1UcXyqQTv82ebDeT03f5LqnuIKVtkvBClA=";
|
||||
};
|
||||
buildInputs = [ compiler npeg ];
|
||||
postInstall = ''
|
||||
pushd $out/bin
|
||||
for link in preserves_decode preserves_from_json preserves_to_json;
|
||||
do ln -s preserves_encode $link
|
||||
done
|
||||
popd
|
||||
'';
|
||||
doCheck = true;
|
||||
}
|
Loading…
Reference in New Issue