ides provides automated, idempotent launching of ephemeral services
in your devshell,
right here, right now.
- ides will instantly launch all your declared services, as soon as you enter the..
- works just like regular mkShell
- full support for
shell.nix,flake.nix, anddirenv
- ides packages and static configs are present only in the nix store
- writable service state defaults under
$XDG_RUNTIME_DIR/ides/<set-id>/ - once shut down all traces effectively disappear
- ides services can only ever run one (1) instance of any package+config combination
- no matter how many times the devshell is opened or the launch command invoked
- ides runs on systemd user services - no additional process manager needed
your dev environment now reproducibly includes your service dependencies!
- bring ides into your nix expression (flake input/fetchGit)
- import it
- optionally provide a
pkgsinstance, mkShell-like function, or ides modules
- optionally provide a
- use ides like a normal
mkShell, but with spicy extras - run
ides stopfor manual teardown; shell leases clean up automatically on exit
here's how:
classic nix(tm) (shell.nix)
let
pkgs = import <nixpkgs> { };
ides = fetchGit {
url = "https://git.atagen.co/atagen/ides";
};
mkIdes = import ides {
# optional instantiation args
inherit pkgs;
shell = pkgs.mkShell.override {
stdenv = pkgs.stdenvNoCC;
};
modules = [ ];
};
in
mkIdes {
# ides-specific options
imports = [ ./caddy.nix ];
services.redis = {
enable = true;
port = 6889;
logLevel = "verbose";
};
# regular mkShell options
nativeBuildInputs = [ pkgs.hello ];
someEnv = "this";
}flake enjoyers (flake.nix)
{
inputs = {
ides.url = "git+https://git.atagen.co/atagen/ides";
};
outputs =
{
nixpkgs,
ides,
...
}:
let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
mkIdes = import ides {
inherit pkgs;
shell = pkgs.mkShell.override {
stdenv = pkgs.stdenvNoCC;
};
modules = [ ];
};
in
{
devShells.x86_64-linux.default = mkIdes {
imports = [ ./caddy.nix ];
services.redis = {
enable = true;
port = 6889;
logLevel = "verbose";
};
nativeBuildInputs = [ pkgs.hello ];
someEnv = "this";
};
};
}concrete service definition (caddy.nix)
{ pkgs, ... }:
{
# as simple as possible
serviceDefs.caddy = {
pkg = pkgs.caddy;
argv = [
"run"
"-c"
{ config = "main"; }
"--adapter"
"caddyfile"
];
configs.main.text = ''
http://*:8888 {
respond "hello"
}
'';
};
}here, we use a simple plaintext config, but ides also supports converting
attribute sets into the following formats (via configs.<name>.content &
configs.<name>.format):
jsonyamltomlinixmlphpjava
configs can also be rendered at service start when they need ephemeral runtime paths:
configs.main.runtime = {
fileName = "service.conf";
parts = [
"data_dir = "
{ runtimePath = "data"; }
"\n"
];
};
argv = [ "--config" { config = "main"; } ];see the provided redis module for an example
for fully commented examples, see here
in case you need manual control, an ides shell provides commands:
ides run: raise the service set manuallyides stop: shut down the service setides restart: do both of the above in successionides status: show service statusides status --json: show unit state, activation units, leases, runtime paths, and config pathsides tui: watch service state, leases, dependency hints, runtime paths, and config pathsides inspect: inspect the generated manifest
Services may also declare lightweight socket, path, or timer activation through
serviceDefs.<name>.socket, .path, or .timer; ides lowers those to
transient user units and keeps its own dependency graph semantics.
see module docs