Skip to content

Commit 5a24b56

Browse files
author
David Arnold
committed
Add mkcert and hostctl instrumentation
1 parent 4859a38 commit 5a24b56

9 files changed

Lines changed: 229 additions & 9 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# mimick use case where users are expected to boostrap their dev ca
2+
# this is also better for testing devhsell ca bootstrapping
3+
dev-ca

devshell.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ packages = [
1616
#
1717
# motd = ""
1818

19+
# This setting helps to add a project's shared *development* root CA
20+
# to host's local trust stores by instrumenting the mkcert third party tool.
21+
# Defining this section also adds `mkcert` to the available packages.
22+
# Set to the path where mkcert-generated CAROOT files are expected to exist
23+
#
24+
# NOTES:
25+
# - be careful to only put *development* certificates under version control
26+
# - create those files with the devshell generated *-install-CA command
27+
# - optionally put this path under .gitignore, if you want users to
28+
# generate certificates themselves on first clone (using *-install-CA)
29+
dev-ca-path = "./dev-ca"
30+
1931
# Use this section to set environment variables to have in the environment.
2032
#
2133
# NOTE: all the values are escaped
@@ -54,3 +66,11 @@ help = "github utility"
5466
name = "hub"
5567
package = "gitAndTools.hub"
5668
category = "utilites"
69+
70+
# These settings help to manage local DNS overrides via
71+
# instrumentation of the hostcl third party tool.
72+
# Defining this section also adds `hostctl` to the available packages.
73+
[static-dns]
74+
"test.domain.local" = "172.0.0.1"
75+
"shared.domain.link-local" = "169.254.0.5"
76+

devshell/config.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ type configCommand struct {
2222
}
2323

2424
type config struct {
25-
Name string `toml:"name"`
26-
Packages []string `toml:"packages"`
27-
Motd *string `toml:"motd"`
28-
Env map[string]interface{} `toml:"env"`
29-
Bash configBash `toml:"bash,omitempty"`
30-
Commands []configCommand `toml:"commands"`
25+
Name string `toml:"name"`
26+
Packages []string `toml:"packages"`
27+
Motd *string `toml:"motd"`
28+
DevCaPath *string `toml:"dev-ca-path,omitempty"`
29+
Env map[string]interface{} `toml:"env"`
30+
Bash configBash `toml:"bash,omitempty"`
31+
Commands []configCommand `toml:"commands"`
32+
StaticDNS map[string]interface{} `toml:"static-dns,omitempty"`
3133
}
3234

3335
func configLoad(path string) (*config, error) {

docs/devshell.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ packages = [
1616
#
1717
# motd = ""
1818

19+
# This setting helps to add a project's shared *development* root CA
20+
# to host's local trust stores by instrumenting the mkcert third party tool.
21+
# Defining this section also adds `mkcert` to the available packages.
22+
# Set to the path where mkcert-generated CAROOT files are expected to exist
23+
#
24+
# NOTES:
25+
# - be careful to only put *development* certificates under version control
26+
# - create those files with the devshell generated *-install-CA command
27+
# - optionally put this path under .gitignore, if you want users to
28+
# generate certificates themselves on first clone (using *-install-CA)
29+
# dev-ca-path = "./dev-ca"
30+
1931
# Use this section to set environment variables to have in the environment.
2032
#
2133
# NOTE: all the values are escaped
@@ -54,3 +66,10 @@ help = "github utility"
5466
name = "hub"
5567
package = "gitAndTools.hub"
5668
category = "utilites"
69+
70+
# These settings help to manage local DNS overrides via
71+
# instrumentation of the hostcl third party tool.
72+
# Defining this section also adds `hostctl` to the available packages.
73+
[static-dns]
74+
"test.domain.local" = "172.0.0.1"
75+
"shared.domain.link-local" = "169.254.0.5"

docs/devshell.toml.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ packages = [
2424
#
2525
# motd = ""
2626

27+
# This setting helps to add a project's shared *development* root CA
28+
# to host's local trust stores by instrumenting the mkcert third party tool.
29+
# Defining this section also adds `mkcert` to the available packages.
30+
# Set to the path where mkcert-generated CAROOT files are expected to exist
31+
#
32+
# NOTES:
33+
# - be careful to only put *development* certificates under version control
34+
# - create those files with the devshell generated *-install-CA command
35+
# - optionally put this path under .gitignore, if you want users to
36+
# generate certificates themselves on first clone (using *-install-CA)
37+
# dev-ca-path = "./dev-ca"
38+
2739
# Use this section to set environment variables to have in the environment.
2840
#
2941
# NOTE: all the values are escaped
@@ -61,6 +73,14 @@ category = "formatters"
6173
help = "github utility"
6274
name = "hub"
6375
package = "gitAndTools.hub"
76+
category = "utilities"
77+
78+
# These settings help to manage local DNS overrides via
79+
# instrumentation of the hostcl third party tool.
80+
# Defining this section also adds `hostctl` to the available packages.
81+
[static-dns]
82+
"test.domain.local" = "172.0.0.1"
83+
"shared.domain.link-local" = "169.254.0.5"
6484
```
6585

6686
## Schema
@@ -84,6 +104,8 @@ The name field is optional and defaults to `devshell`.
84104

85105
### The `motd` field
86106

107+
### The `dev-ca-path` field
108+
87109
### The `env` section
88110

89111
### The `bash.extra` field
@@ -97,3 +119,5 @@ The name field is optional and defaults to `devshell`.
97119
* `name`:
98120
* `package`:
99121

122+
### The `static-dns` section
123+

hostctl/default.nix

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{ buildGoModule, fetchFromGitHub, lib, installShellFiles }:
2+
3+
buildGoModule rec {
4+
pname = "hostctl";
5+
version = "1.0.14";
6+
7+
src = fetchFromGitHub {
8+
owner = "guumaster";
9+
repo = pname;
10+
rev = "v${version}";
11+
sha256 = "02bjii97l4fy43v2rb93m9b0ad8y6mjvbvp4sz6a5n0w9dm1z1q9";
12+
};
13+
14+
vendorSha256 = "1lqk3cda0frqp2vwkqa4b3xkdw814wgkbr7g9r2mwxn85fpdcq5c";
15+
16+
doCheck = false;
17+
buildFlagsArray = [ "-ldflags=-s -w -X github.com/guumaster/hostctl/cmd/hostctl/actions.version=${version}" ];
18+
19+
nativeBuildInputs = [ installShellFiles ];
20+
postInstall = ''
21+
$out/bin/hostctl completion bash > hostctl.bash
22+
$out/bin/hostctl completion zsh > hostctl.zsh
23+
installShellCompletion hostctl.{bash,zsh}
24+
# replace above by following once merged https://github.com/NixOS/nixpkgs/pull/83630
25+
# installShellCompletion --cmd hostctl \
26+
# --bash <($out/bin/hostctl completion bash) \
27+
# --zsh <($out/bin/hostctl completion zsh)
28+
'';
29+
30+
meta = with lib; {
31+
description = "Your dev tool to manage /etc/hosts like a pro!";
32+
longDescription = ''
33+
This tool gives you more control over the use of your hosts file.
34+
You can have multiple profiles and switch them on/off as you need.
35+
'';
36+
homepage = "https://guumaster.github.io/hostctl/";
37+
license = licenses.mit;
38+
maintainers = with maintainers; [ blaggacao ];
39+
};
40+
}

mkDevShell/instrumentation.nix

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{ lib, pkgs, config }:
2+
let
3+
inherit (config)
4+
name
5+
dev-ca-path
6+
static-dns
7+
;
8+
installProjectCA = {
9+
name = "ca-install";
10+
help = "install dev CA";
11+
category = "host state";
12+
package = pkgs.mkcert;
13+
command = ''
14+
echo "$(tput bold)Installing the ${name}'s dev CA into local trust stores via mkcert command ...$(tput sgr0)"
15+
export CAROOT=${dev-ca-path}
16+
${pkgs.mkcert}/bin/mkcert -install
17+
'';
18+
};
19+
uninstallProjectCA = {
20+
name = "ca-uninstall";
21+
help = "uninstall dev CA";
22+
category = "host state";
23+
package = pkgs.mkcert;
24+
command = ''
25+
echo "$(tput bold)Purging the ${name}'s dev CA from local trust stores via mkcert command ...$(tput sgr0)"
26+
export CAROOT=${dev-ca-path}
27+
${pkgs.mkcert}/bin/mkcert -uninstall
28+
'';
29+
};
30+
31+
etcHosts = pkgs.writeText "${name}-etchosts"
32+
(lib.concatStringsSep "\n"
33+
(lib.mapAttrsToList (name: value: value + " " + name) static-dns)
34+
);
35+
# since this temporarily modifies /etc/hosts, use of sudo can't be avoided
36+
fqdnsActivate = {
37+
name = "dns-activate";
38+
category = "host state";
39+
help = "activate pre-configured static dns";
40+
package = pkgs.hostctl;
41+
command = ''
42+
echo "$(tput bold)Installing ${name}'s static local DNS resolution via hostctl command ...$(tput sgr0)"
43+
sudo ${pkgs.hostctl}/bin/hostctl add ${name} --from ${etcHosts}
44+
'';
45+
};
46+
fqdnsDeactivate = {
47+
name = "dns-deactivate";
48+
category = "host state";
49+
help = "deactivate pre-configured static dns";
50+
package = pkgs.hostctl;
51+
command = ''
52+
echo "$(tput bold)Purging ${name}'s static local DNS resolution via hostctl command ...$(tput sgr0)"
53+
sudo ${pkgs.hostctl}/bin/hostctl remove ${name}
54+
'';
55+
};
56+
in
57+
(
58+
if static-dns == null || static-dns == "" then [ ]
59+
else [ fqdnsActivate fqdnsDeactivate ]
60+
) ++
61+
(
62+
if dev-ca-path == null || dev-ca-path == "" then [ ]
63+
else [ installProjectCA uninstallProjectCA ]
64+
)

mkDevShell/options.nix

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{ lib, pkgs, config, ... }:
22
with lib;
33
let
4+
instrumentedCommands = import ./instrumentation.nix { inherit lib pkgs config; };
5+
46
resolveKey = key:
57
let
68
attrs = builtins.filter builtins.isString (builtins.split "\\." key);
@@ -137,6 +139,27 @@ in
137139
'';
138140
};
139141

142+
# exclusively consumed by command instrumentation
143+
dev-ca-path = mkOption {
144+
type = types.str;
145+
default = "";
146+
description = ''
147+
Path to a development CA.
148+
149+
Users can load/unload this dev CA easily and cleanly into their local
150+
trust stores via a wrapper around mkcert third party tool so that browsers
151+
and other tools would accept issued certificates under this CA as valid.
152+
153+
Use cases:
154+
- Ship static dev certificates under version control and make them trusted
155+
on user machines: add the rootCA under version control alongside the
156+
your dev certificates.
157+
- Provide users with easy and reliable CA bootstrapping through the mkcert
158+
command: exempt this path from version control via .gitignore and have
159+
users easily and reliably bootstrap a dev CA infrastructure on first use.
160+
'';
161+
};
162+
140163
commands = mkOption {
141164
type = types.listOf (types.submodule { options = commandOptions; });
142165
default = [ ];
@@ -210,6 +233,23 @@ in
210233
'';
211234
};
212235

236+
# exclusively consumed by command instrumentation
237+
static-dns = mkOption {
238+
type = types.attrs;
239+
default = { };
240+
description = ''
241+
A list of static DNS entries, for which to enable instrumentation.
242+
243+
Users can enable/disable listed static DNS easily and cleanly
244+
via a wrapper around the hostctl third party tool.
245+
'';
246+
example = {
247+
"test.domain.local" = "172.0.0.1";
248+
"shared.domain.link-local" = "169.254.0.5";
249+
};
250+
};
251+
252+
213253
};
214254

215255
config = {
@@ -223,10 +263,17 @@ in
223263
DEVSHELL_MENU
224264
'';
225265
}
226-
];
266+
] ++ instrumentedCommands;
227267

228268
packages =
229-
builtins.filter (x: x != null)
230-
(map (x: x.package) config.commands);
269+
lib.unique (
270+
builtins.filter
271+
(x: x != null)
272+
(
273+
map
274+
(x: x.package)
275+
config.commands
276+
)
277+
);
231278
};
232279
}

overlay.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ final: prev:
22
{
33
devshell = prev.callPackage ./devshell { };
44
mkDevShell = prev.callPackage ./mkDevShell { };
5+
hostctl = prev.callPackage ./hostctl { };
56
}

0 commit comments

Comments
 (0)