difftreelog
refactor nix secret module
in: trunk
17 files changed
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,7 @@
[workspace]
members = ["crates/*", "cmds/*"]
resolver = "2"
+package.version = "0.1.0"
[workspace.dependencies]
nixlike = { path = "./crates/nixlike" }
cmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/secrets/mod.rs
+++ b/cmds/fleet/src/cmds/secrets/mod.rs
@@ -1,6 +1,5 @@
use crate::{
better_nix_eval::Field,
- command::MyCommand,
fleetdata::{FleetSecret, FleetSharedSecret, SecretData},
host::Config,
nix_go, nix_go_json,
@@ -9,16 +8,14 @@
use chrono::{DateTime, Utc};
use clap::Parser;
use owo_colors::OwoColorize;
-use serde::{de::DeserializeOwned, Deserialize};
+use serde::Deserialize;
use std::{
collections::{BTreeSet, HashSet},
io::{self, Cursor, Read},
- path::{Path, PathBuf},
- str::FromStr,
+ path::PathBuf,
};
use tabled::{Table, Tabled};
-use tempfile::tempdir;
-use tokio::fs::{self, read_to_string};
+use tokio::fs::read_to_string;
use tracing::{error, info, info_span, warn, Instrument};
#[derive(Parser)]
@@ -162,84 +159,13 @@
}
async fn generate_pure(
- config: &Config,
+ _config: &Config,
_display_name: &str,
- secret: Field,
- default_generator: Field,
- owners: &[String],
+ _secret: Field,
+ _default_generator: Field,
+ _owners: &[String],
) -> Result<FleetSecret> {
- // TODO: pure secrets are supposed to be generated by nix daemon itself,
- // inside of a sandbox... But we aren't here yet.
- let config_field = &config.config_unchecked_field;
- let generator = nix_go!(secret.generator);
- let default_pkgs = &config.default_pkgs;
-
- let call_package = nix_go!(default_pkgs.callPackage);
-
- let generator = nix_go!(call_package(generator)(Obj {}));
- let generator = generator.build().await?;
- let generator = generator
- .get("out")
- .ok_or_else(|| anyhow!("missing generate out"))?;
-
- let mut recipients = String::new();
- for owner in owners {
- let key = config.key(owner).await?;
- recipients.push_str(&format!("-r \"{key}\" "));
- }
- recipients.push_str("-e");
-
- let out = tempdir()?;
-
- let mut gen = MyCommand::new(generator);
- gen.env("rageArgs", recipients);
- gen.env(
- "out",
- out.path().to_str().expect("sane tempdir should be utf-8"),
- );
- gen.run().await.context("impure generator")?;
-
- {
- let mut marker_path = out.path().to_owned();
- marker_path.push("marker");
- let marker = fs::read_to_string(&marker_path).await?;
- ensure!(marker == "SUCCESS", "generation not succeeded");
- }
-
- let mut public_path = out.path().to_owned();
- public_path.push("public");
- let mut secret_path = out.path().to_owned();
- secret_path.push("secret");
- let public = fs::read_to_string(&public_path).await.ok();
- let secret = fs::read(&secret_path).await.ok();
- if let Some(secret) = &secret {
- ensure!(
- age::Decryptor::new(Cursor::new(&secret)).is_ok(),
- "builder produced non-encrypted value as secret, this is highly insecure, and not allowed."
- );
- }
-
- let mut created_at_path = out.path().to_owned();
- created_at_path.push("created_at");
- let mut expires_at_path = out.path().to_owned();
- expires_at_path.push("expires_at");
-
- async fn read_value<T: FromStr>(path: &Path) -> Result<T> {
- dbg!(path);
- let raw = fs::read(path).await?;
- let raw = String::from_utf8(raw)?;
- raw.parse().map_err(|_| anyhow!("fromStr failed"))
- }
-
- let created_at = read_value(&created_at_path).await?;
- let expires_at = read_value(&expires_at_path).await.ok();
-
- Ok(FleetSecret {
- created_at,
- expires_at,
- public,
- secret: secret.map(SecretData),
- })
+ bail!("pure generators are broken for now")
}
async fn generate_impure(
config: &Config,
@@ -248,39 +174,53 @@
default_generator: Field,
owners: &[String],
) -> Result<FleetSecret> {
- let config_field = &config.config_unchecked_field;
let generator = nix_go!(secret.generator);
+ let on: Option<String> = nix_go_json!(default_generator.impureOn);
- let on: String = nix_go_json!(default_generator.impureOn);
- let call_package = nix_go!(
- config_field.hosts[{ on }]
- .nixosSystem
- .config
- .nixpkgs
- .resolvedPkgs
- .callPackage
- );
+ let host = if let Some(on) = &on {
+ config.host(on).await?
+ } else {
+ config.local_host()
+ };
+ let on_pkgs = host.pkgs().await?;
+ let call_package = nix_go!(on_pkgs.callPackage);
+ let mk_encrypt_secret = nix_go!(on_pkgs.mkEncryptSecret);
- let host = config.host(&on).await?;
+ let mut recipients = Vec::new();
+ for owner in owners {
+ let key = config.key(owner).await?;
+ recipients.push(key);
+ }
+ let encrypt = nix_go!(mk_encrypt_secret(Obj {
+ recipients: { recipients },
+ }));
+
+ let generator = nix_go!(call_package(generator)(Obj {
+ encrypt,
+ rustfmt_please_newline: { true },
+ }));
- let generator = nix_go!(call_package(generator)(Obj {}));
let generator = generator.build().await?;
let generator = generator
.get("out")
.ok_or_else(|| anyhow!("missing generateImpure out"))?;
let generator = host.remote_derivation(generator).await?;
- let mut recipients = String::new();
- for owner in owners {
- let key = config.key(owner).await?;
- recipients.push_str(&format!("-r \"{key}\" "));
- }
- recipients.push_str("-e");
-
- let out = host.mktemp_dir().await?;
+ let out_parent = host.mktemp_dir().await?;
+ let out = format!("{out_parent}/out");
let mut gen = host.cmd(generator).await?;
- gen.env("rageArgs", recipients).env("out", &out);
+ gen.env("out", &out);
+ if on.is_none() {
+ // This path is local, thus we can feed `OsString` directly to env var... But I don't think that's necessary to handle.
+ let project_path: String = config
+ .directory
+ .clone()
+ .into_os_string()
+ .into_string()
+ .map_err(|s| anyhow!("fleet project path is not utf-8: {s:?}"))?;
+ gen.env("FLEET_PROJECT", project_path);
+ }
gen.run().await.context("impure generator")?;
{
@@ -549,10 +489,7 @@
println!("{}", z85::encode(&data));
}
}
- Secret::ReadPublic {
- name,
- machine,
- } => {
+ Secret::ReadPublic { name, machine } => {
let secret = config.host_secret(&machine, &name)?;
let Some(public) = secret.public else {
bail!("no secret {name}");
cmds/fleet/src/host.rsdiffbeforeafterboth--- a/cmds/fleet/src/host.rs
+++ b/cmds/fleet/src/host.rs
@@ -54,7 +54,7 @@
pub local: bool,
pub session: OnceLock<Arc<openssh::Session>>,
- pub nixos_config: Field,
+ pub nixos_config: Option<Field>,
}
impl ConfigHost {
async fn open_session(&self) -> Result<Arc<openssh::Session>> {
@@ -169,7 +169,9 @@
}
pub async fn list_configured_secrets(&self) -> Result<Vec<String>> {
- let nixos = &self.nixos_config;
+ let Some(nixos) = &self.nixos_config else {
+ return Ok(vec![]);
+ };
let secrets = nix_go!(nixos.secrets);
let mut out = Vec::new();
for name in secrets.list_fields().await? {
@@ -183,9 +185,19 @@
Ok(out)
}
pub async fn secret_field(&self, name: &str) -> Result<Field> {
- let nixos = &self.nixos_config;
+ let Some(nixos) = &self.nixos_config else {
+ bail!("host is virtual and has no secrets");
+ };
Ok(nix_go!(nixos.secrets[{ name }]))
}
+
+ /// Packages for this host, resolved with nixpkgs overlays
+ pub async fn pkgs(&self) -> Result<Field> {
+ let Some(nixos) = &self.nixos_config else {
+ return Ok(self.config.default_pkgs.clone());
+ };
+ Ok(nix_go!(nixos.nixpkgs.resolvedPkgs))
+ }
}
impl Config {
@@ -202,6 +214,16 @@
self.opts.localhost.as_ref().map(|s| s as &str) == Some(host)
}
+ pub fn local_host(&self) -> ConfigHost {
+ ConfigHost {
+ config: self.clone(),
+ name: "<virtual localhost>".to_owned(),
+ local: true,
+ session: OnceLock::new(),
+ nixos_config: None,
+ }
+ }
+
pub async fn host(&self, name: &str) -> Result<ConfigHost> {
let config = &self.config_unchecked_field;
let nixos_config = nix_go!(config.hosts[{ name }].nixosSystem.config);
@@ -210,7 +232,7 @@
name: name.to_owned(),
local: self.is_local(name),
session: OnceLock::new(),
- nixos_config,
+ nixos_config: Some(nixos_config),
})
}
pub async fn list_hosts(&self) -> Result<Vec<ConfigHost>> {
cmds/fleet/src/main.rsdiffbeforeafterboth--- a/cmds/fleet/src/main.rs
+++ b/cmds/fleet/src/main.rs
@@ -11,7 +11,6 @@
mod fleetdata;
-use std::time::Duration;
use std::{ffi::OsString, process::ExitCode};
use anyhow::{bail, Result};
@@ -158,7 +157,7 @@
let reg = tracing_subscriber::registry().with({
let sub = tracing_subscriber::fmt::layer()
.without_time()
- .with_target(true);
+ .with_target(false);
#[cfg(feature = "indicatif")]
let sub = sub.with_writer(indicatif_layer.get_stdout_writer());
sub.with_filter(filter) // .withou,
cmds/install-secrets/src/main.rsdiffbeforeafterboth--- a/cmds/install-secrets/src/main.rs
+++ b/cmds/install-secrets/src/main.rs
@@ -13,7 +13,7 @@
use std::path::Path;
use std::str::{from_utf8, FromStr};
use std::{collections::HashMap, path::PathBuf};
-use tracing::{error, info, warn};
+use tracing::{error, info, info_span, warn};
use tracing_subscriber::filter::LevelFilter;
use tracing_subscriber::EnvFilter;
@@ -213,12 +213,9 @@
let mut failed = false;
for (name, value) in data {
- info!("initializing secret {name}");
+ let _span = info_span!("init", name = name);
if let Err(e) = init_secret(&identity, value) {
- error!(
- "{:?}",
- e.context(format!("failed to initialize secret {}", name))
- );
+ error!("{e}");
failed = true;
}
}
@@ -237,6 +234,7 @@
.from_env_lossy(),
)
.without_time()
+ .with_target(false)
.init();
let opts = Opts::parse();
crates/better-command/src/handler.rsdiffbeforeafterboth--- a/crates/better-command/src/handler.rs
+++ b/crates/better-command/src/handler.rs
@@ -274,7 +274,10 @@
#[cfg(feature = "indicatif")]
span.pb_set_message(&process_message(s.trim()));
#[cfg(not(feature = "indicatif"))]
- info!("{}", process_message(s));
+ {
+ let _span = span.enter();
+ info!("{}", process_message(s));
+ }
} else {
warn!("bad fields: {fields:?}");
}
crates/better-command/src/lib.rsdiffbeforeafterboth--- a/crates/better-command/src/lib.rs
+++ b/crates/better-command/src/lib.rs
@@ -1,5 +1,5 @@
mod handler;
-pub use handler::{Handler, PlainHandler, NoopHandler, NixHandler, ClonableHandler};
+pub use handler::{ClonableHandler, Handler, NixHandler, NoopHandler, PlainHandler};
pub fn add(left: usize, right: usize) -> usize {
left + right
flake.lockdiffbeforeafterboth--- a/flake.lock
+++ b/flake.lock
@@ -1,26 +1,28 @@
{
"nodes": {
- "flake-utils": {
+ "crane": {
"inputs": {
- "systems": "systems"
+ "nixpkgs": [
+ "nixpkgs"
+ ]
},
"locked": {
- "lastModified": 1705309234,
- "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
- "owner": "numtide",
- "repo": "flake-utils",
- "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
+ "lastModified": 1712681629,
+ "narHash": "sha256-bMDXn4AkTXLCpoZbII6pDGoSeSe9gI87jxPsHRXgu/E=",
+ "owner": "ipetkov",
+ "repo": "crane",
+ "rev": "220387ac8e99cbee0ca4c95b621c4bc782b6a235",
"type": "github"
},
"original": {
- "owner": "numtide",
- "repo": "flake-utils",
+ "owner": "ipetkov",
+ "repo": "crane",
"type": "github"
}
},
- "flake-utils_2": {
+ "flake-utils": {
"inputs": {
- "systems": "systems_2"
+ "systems": "systems"
},
"locked": {
"lastModified": 1705309234,
@@ -54,6 +56,7 @@
},
"root": {
"inputs": {
+ "crane": "crane",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
@@ -61,7 +64,9 @@
},
"rust-overlay": {
"inputs": {
- "flake-utils": "flake-utils_2",
+ "flake-utils": [
+ "flake-utils"
+ ],
"nixpkgs": [
"nixpkgs"
]
@@ -81,21 +86,6 @@
}
},
"systems": {
- "locked": {
- "lastModified": 1681028828,
- "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
- "owner": "nix-systems",
- "repo": "default",
- "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
- "type": "github"
- },
- "original": {
- "owner": "nix-systems",
- "repo": "default",
- "type": "github"
- }
- },
- "systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
flake.nixdiffbeforeafterboth--- a/flake.nix
+++ b/flake.nix
@@ -5,15 +5,23 @@
nixpkgs.url = "github:nixos/nixpkgs/master";
rust-overlay = {
url = "github:oxalica/rust-overlay";
+ inputs = {
+ nixpkgs.follows = "nixpkgs";
+ flake-utils.follows = "flake-utils";
+ };
+ };
+ flake-utils.url = "github:numtide/flake-utils";
+ crane = {
+ url = "github:ipetkov/crane";
inputs.nixpkgs.follows = "nixpkgs";
};
- flake-utils = {url = "github:numtide/flake-utils";};
};
outputs = {
self,
rust-overlay,
flake-utils,
nixpkgs,
+ crane,
}:
with nixpkgs.lib;
{
@@ -26,20 +34,16 @@
inherit system;
overlays = [(import rust-overlay)];
};
- llvmPkgs = pkgs.buildPackages.llvmPackages_11;
- rust =
- (pkgs.rustChannelOf {
- date = "2024-02-10";
- channel = "nightly";
- })
- .default
- .override {extensions = ["rust-src" "rust-analyzer"];};
+ rust = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
+ craneLib = (crane.mkLib pkgs).overrideToolchain rust;
in {
- packages = (import ./pkgs) pkgs pkgs;
- devShell = (pkgs.mkShell.override {stdenv = llvmPkgs.stdenv;}) {
+ packages = import ./pkgs {
+ inherit (pkgs) callPackage;
+ inherit craneLib;
+ };
+ devShell = craneLib.devShell {
nativeBuildInputs = with pkgs; [
alejandra
- rust
lld
cargo-edit
cargo-udeps
lib/default.nixdiffbeforeafterboth--- a/lib/default.nix
+++ b/lib/default.nix
@@ -10,11 +10,14 @@
hosts,
modules,
globalModules ? [],
+ extraFleetLib ? {},
}: let
hostNames = nixpkgs.lib.attrNames hosts;
- fleetLib = import ./fleetLib.nix {
- inherit nixpkgs hostNames;
- };
+ fleetLib =
+ (import ./fleetLib.nix {
+ inherit nixpkgs hostNames;
+ })
+ // extraFleetLib;
in let
root = nixpkgs.lib.evalModules {
modules =
lib/fleetLib.nixdiffbeforeafterboth--- a/lib/fleetLib.nix
+++ b/lib/fleetLib.nix
@@ -39,4 +39,32 @@
mkFleetDefault = mkOverride 999;
# Some generators use mkDefault, but optionDefault is set by nixpkgs.
mkFleetGeneratorDefault = mkOverride 1001;
+
+ mkPassword = {size ? 32}: {
+ coreutils,
+ encrypt,
+ mkSecretGenerator,
+ }:
+ mkSecretGenerator {
+ script = ''
+ ${coreutils}/bin/tr -dc 'A-Za-z0-9!?%=' < /dev/random \
+ | ${coreutils}/bin/head -c ${toString size} \
+ | ${encrypt} > $out/secret
+ '';
+ };
+
+ mkRsa = {size ? 4096}: {
+ openssl,
+ encrypt,
+ mkSecretGenerator,
+ }:
+ mkSecretGenerator {
+ script = ''
+ ${openssl}/bin/openssl genrsa -out rsa_private.key ${toString size}
+ ${openssl}/bin/openssl rsa -in rsa_private.key -pubout -out rsa_public.key
+
+ sudo cat rsa_private.key | ${encrypt} > $out/secret
+ sudo cat rsa_public.key > $out/public
+ '';
+ };
}
modules/fleet/secrets.nixdiffbeforeafterboth1{2 lib,3 fleetLib,4 config,5 ...6}:7with lib;8with fleetLib; let9 sharedSecret = with types; ({config, ...}: {10 options = {11 expectedOwners = mkOption {12 type = nullOr (listOf str);13 description = ''14 List of hosts to encrypt secret for. null if managed by user (= via owners field from fleet.nix)1516 Secrets would be decrypted and stored to /run/secrets/$\{name} on owners17 '';18 default = null;19 };20 # TODO: Aren't those options may be just desugared to data/expectedData?21 regenerateOnOwnerAdded = mkOption {22 type = bool;23 description = ''24 Is this secret owner-dependent, and needs to be regenerated on ownership set change, or it may be just reencrypted.2526 You want to have this option set to true, when this secret contains some reference to its owners, i.e x509 SANs.27 '';28 };29 regenerateOnOwnerRemoved = mkOption {30 default = config.regenerateOnOwnerAdded;31 type = bool;32 description = ''33 Should this secret be removed on owner removal, or it may be just reencrypted3435 Most probably its value should be equal to regenerateOnOwnerAdded, override only if you know what are you doing.36 Contrary to regenerateOnOwnerAdded, you may want to set this option to false, when host permissions are revoked37 in some other way than by this secret ownership, I.e by firewall/etc.38 '';39 };40 generator = mkOption {41 type = nullOr unspecified;42 description = "Derivation to evaluate for secret generation";43 default = null;44 };45 createdAt = mkOption {46 type = nullOr str;47 description = "When this secret was (re)generated";48 default = null;49 };50 expiresAt = mkOption {51 type = nullOr str;52 description = "On which date this secret will expire, someone should regenerate this secret before it expires.";53 default = null;54 };5556 owners = mkOption {57 type = listOf str;58 description = ''59 For which owners this secret is currently encrypted,60 if not matches expectedOwners - then this secret is considered outdated, and61 should be regenerated/reencrypted.6263 Imported from fleet.nix64 '';65 default = [];66 };67 # TODO: Make secret generator generate arbitrary number of secret/public parts?68 # Make it generate a folder, where all files except suffixed by .enc are public, and the rest are secret?69 # How should modules refer to those files then?70 public = mkOption {71 type = nullOr str;72 description = "Secret public data. Imported from fleet.nix";73 default = null;74 };75 secret = mkOption {76 type = nullOr str;77 description = "Encrypted secret data. Imported from fleet.nix";78 default = null;79 internal = true;80 };81 };82 });83 hostSecret = with types; {84 options = {85 createdAt = mkOption {86 type = nullOr str;87 default = null;88 };89 expiresAt = mkOption {90 type = nullOr str;91 default = null;92 };93 public = mkOption {94 type = nullOr str;95 description = "Secret public data. Imported from fleet.nix";96 default = null;97 };98 secret = mkOption {99 type = nullOr str;100 description = "Encrypted secret data. Imported from fleet.nix";101 default = null;102 internal = true;103 };104 };105 };106in {107 options = with types; {108 sharedSecrets = mkOption {109 type = attrsOf (submodule sharedSecret);110 default = {};111 description = "Shared secrets";112 };113 hostSecrets = mkOption {114 type = attrsOf (attrsOf (submodule hostSecret));115 default = {};116 description = "Host secrets. Imported from fleet.nix";117 internal = true;118 };119 };120 config = {121 assertions =122 mapAttrsToList123 (name: secret: {124 assertion = secret.expectedOwners == null || builtins.sort (a: b: a < b) secret.owners == builtins.sort (a: b: a < b) secret.expectedOwners;125 message = "Shared secret ${name} is expected to be encrypted for ${builtins.toJSONsecret.expectedOwners}, but it is encrypted for ${builtins.toJSONsecret.owners}. Run fleet secrets regenerate to fix";126 })127 config.sharedSecrets;128 hosts = hostsToAttrs (host: {129 modules = let130 cleanupSecret = secretName: v: {131 inherit (v) public secret;132 shared = true;133 };134 in [135 {136 secrets =137 (138 mapAttrs cleanupSecret139 (filterAttrs (_: v: builtins.elem host v.owners) config.sharedSecrets)140 )141 // (mapAttrs cleanupSecret (config.hostSecrets.${host} or {}));142 }143 ];144 });145 # TODO: Should this attribute be moved to `nixpkgs.overlays`?146 overlays = [147 (final: prev: let148 lib = final.lib;149 in {150 mkPassword = {size ? 32}:151 final.mkSecretGenerator ''152 ${final.coreutils}/bin/tr -dc 'A-Za-z0-9!?%=' < /dev/random \153 | ${final.coreutils}/bin/head -c ${toStringsize} \154 | encrypt > $out/secret155 '';156 mkRsa = {size ? 4096}:157 final.mkSecretGenerator ''158 ${final.openssl}/bin/openssl genrsa -out rsa_private.key ${toStringsize}159 ${final.openssl}/bin/openssl rsa -in rsa_private.key -pubout -out rsa_public.key160161 sudo cat rsa_private.key | encrypt > $out/secret162 sudo cat rsa_public.key > $out/public163 '';164 # TODO: Move to fleet165 # TODO: Merge both generators to one with consistent options syntax?166 # Impure generator is built on local machine, then built closure is copied to remote machine,167 # and then it is ran in inpure context, so that this generator may access HSMs and other things.168 mkImpureSecretGenerator = generatorText: machine:169 (prev.writeShellScript "impureGenerator.sh" ''170 #!/bin/sh171 set -eu172173 # TODO: Provide encryption function as script passed to `callPackage generator {encrypt = ...;}`174 function encrypt() {175 eval ${final.rage}/bin/rage $rageArgs176 }177178 created_at=date-u"%Y-%m-%dT%H:%M:%S.%NZ"179 echo -n $created_at > $out/created_at180181 ${generatorText}182183 echo -n SUCCESS > $out/marker184 '')185 .overrideAttrs (old: {186 passthru = {187 generatorKind = "impure";188 impureOn = machine;189 };190 });191 # TODO: Implement consistent naming192 # Pure secret generator is supposed to be run entirely by nix, using `__impure` derivation type...193 # But for now, it is ran the same way as `impureSecretGenerator`, but on the local machine.194 mkSecretGenerator = generatorText:195 (prev.writeShellScript "generator.sh" ''196 #!/bin/sh197 set -eu198 # TODO: User should create output directory by themselves.199 cd $out200201 # TODO: Provide encryption function as script passed to `callPackage generator {encrypt = ...;}`202 function encrypt() {203 eval ${final.rage}/bin/rage $rageArgs204 }205206 created_at=date-u"%Y-%m-%dT%H:%M:%S.%NZ"207 echo -n $created_at > $out/created_at208209 ${generatorText}210211 echo -n SUCCESS > $out/marker212 '')213 .overrideAttrs (old: {214 passthru = {215 generatorKind = "pure";216 };217 # TODO: make nix daemon build secret, not just the script.218 # __impure = true;219 });220 })221 ];222 };223}nixos/fleetPkgs.nixdiffbeforeafterboth--- a/nixos/fleetPkgs.nix
+++ b/nixos/fleetPkgs.nix
@@ -1,3 +1,24 @@
-{ ... }: {
- nixpkgs.overlays = [ (import ../pkgs) ];
+{...}: {
+ nixpkgs.overlays = [
+ # Not using craneLib here, because we don't want to have two different rust versions for some platforms.
+ (final: prev: {
+ fleet-install-secrets = prev.callPackage ({rustPlatform}:
+ rustPlatform.buildRustPackage rec {
+ pname = "fleet-install-secrets";
+ name = "${pname}";
+
+ src = ../.;
+ strictDeps = true;
+
+ buildAndTestSubdir = "cmds/install-secrets";
+
+ cargoLock = {
+ lockFile = ../Cargo.lock;
+ outputHashes = {
+ "alejandra-3.0.0" = "sha256-lStDIPizbJipd1JpNKX1olBKzyIosyC2U/mVFwJPcZE=";
+ };
+ };
+ }) {};
+ })
+ ];
}
pkgs/default.nixdiffbeforeafterboth--- a/pkgs/default.nix
+++ b/pkgs/default.nix
@@ -1,6 +1,9 @@
-pkgs: super:
-with pkgs;
{
- fleet-install-secrets = callPackage ./fleet-install-secrets.nix { };
- fleet = callPackage ./fleet.nix { };
+ callPackage,
+ craneLib,
+}: rec {
+ default = fleet;
+
+ fleet-install-secrets = callPackage ./fleet-install-secrets.nix {inherit craneLib;};
+ fleet = callPackage ./fleet.nix {inherit craneLib;};
}
pkgs/fleet-install-secrets.nixdiffbeforeafterboth--- a/pkgs/fleet-install-secrets.nix
+++ b/pkgs/fleet-install-secrets.nix
@@ -1,16 +1,9 @@
-{ rustPlatform, lib }:
-
-rustPlatform.buildRustPackage rec {
+{craneLib}:
+craneLib.buildPackage rec {
pname = "fleet-install-secrets";
- version = "0.0.1";
- name = "${pname}-${version}";
- src = ../.;
- buildAndTestSubdir = "cmds/install-secrets";
- cargoLock = {
- lockFile = ../Cargo.lock;
- outputHashes = {
- "alejandra-3.0.0" = "sha256-lStDIPizbJipd1JpNKX1olBKzyIosyC2U/mVFwJPcZE=";
- };
- };
+ src = craneLib.cleanCargoSource (craneLib.path ../.);
+ strictDeps = true;
+
+ cargoExtraArgs = "--locked -p ${pname}";
}
pkgs/fleet.nixdiffbeforeafterboth--- a/pkgs/fleet.nix
+++ b/pkgs/fleet.nix
@@ -1,16 +1,9 @@
-{ rustPlatform }:
-
-rustPlatform.buildRustPackage rec {
+{craneLib}:
+craneLib.buildPackage rec {
pname = "fleet";
- version = "0.0.1";
- name = "${pname}-${version}";
- src = ../.;
- cargoBuildFlags = "-p ${pname}";
- cargoLock = {
- lockFile = ../Cargo.lock;
- outputHashes = {
- "alejandra-3.0.0" = "sha256-YSdHsJ73G7TEFzbmpZ2peuMefIa9/vNB2g+xdiyma3U=";
- };
- };
+ src = craneLib.cleanCargoSource (craneLib.path ../.);
+ strictDeps = true;
+
+ cargoExtraArgs = "--locked -p ${pname}";
}
rust-toolchain.tomldiffbeforeafterboth--- /dev/null
+++ b/rust-toolchain.toml
@@ -0,0 +1,3 @@
+[toolchain]
+channel = "nightly-2024-02-10"
+components = ["rustfmt", "clippy", "rust-analyzer", "rust-src"]