Skip to content

A proof of concept project for defining NixOS containers (systemd-nspawn) in a flake.nix file.

License

Notifications You must be signed in to change notification settings

adfaure/flake-containers

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

flake-containers

Introduction

A proof of concept project for defining NixOS containers (systemd-nspawn) in a flake.nix file.

Description

"flake-containers" is a small project demonstrating the usage of Nix for managing systemd containers. It utilizes the Nix language and the Nix flake system to define and launch containers with systemd-nspawn.

Features

  • Define systemd containers in Nix.
  • Generate commands to manage the containers (mostly wrappers around machinectl, instead of the ups commands).

Why?

As stated, this is a proof of concept. I created it for experimenting with systemd-nspawn, NixOS, and flake-parts.

That being said, in my development workflow, I almost always define my development dependencies into a flake for Rust, Python, Go, etc. When I need to use different services, such as a database, I would typically rely on Docker. However, with flake-containers, I can directly benefit from NixOS services and enable and configure the services that I need, in a reproducible and shareable way.

It's worth mentioning that while there already exists a way to manage NixOS containers using nixos-container, it integrates within a NixOS configuration. This project has been largely inspired by nixos-containers (in fact, most of the code comes from there). However, flake-containers enables the definition and management of NixOS containers without the need to update your system configuration. Furthermore, it should work on any Linux distribution with Nix installed.

Limitations

  • It requires root privileges to start the containers.
  • nixpkgs can be configured with a config and overlays, even changing the nixpkgs source. However, it cannot be set on a per container basis, and it is effective for each containers.
  • There is a dependency on flake-roots to retrieve the path for the project, where I store the states for the containers.
  • I dont think that the container can be updated while alive (with with nixos-rebuild switch for instance).

Future Works

  • It is not a compose-style project (at least for now); there is one command per container. No "flake-containers up" command.
  • No support for volumes (temporary or permanent).
    • Volumes can be configured now in nix, but why not adding the possibility to specify volumes in the command line ?
  • The network configuration is currently simple and not configurable (no support for bridges for instance).
  • Compatibility with other distributions is untested; it has only been tested on NixOS.
  • The project lacks testing. It appears to work on my computer; that's the only guarantee I can offer at the moment.
  • There is an ugly sleep at the start time. I need a better way to detect when a container is alive to start the network configuration.
  • Better nix code (add comments and types)
  • Create a script to clean container states directory: NixOS/nixpkgs#63028 (comment)
  • Add an ephemeral mode
    • see --ephemeral on systemd-npsawn ?
    • manually setting up tmpfs ?
  • Add comparison with devenv, nix2containers, nixos-compose
  • Create a better way to specify run commands
  • Create a way to easily define testscripts (same as in nixos)
  • Find a way to transfer ownership inside the container (so for instance, when running commands from inside the container, we don't end up with a lot of root files in the host system)

Usage

  1. Start by creating a flake with the following content:
    {
        inputs = {
            nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
            # This project is based on flake-parts, so you need to import it
            flake-parts.url = "github:hercules-ci/flake-parts";
            # flake-root is a dependency that enable to find the root project for the flake
            # repositorty to create the states for the containers
            flake-root.url = "github:srid/flake-root";
            # Import flake-containers
            flake-containers.url = "github:adfaure/flake-containers";
        };
        outputs =
            inputs@{ self, nixpkgs, flake-parts, flake-containers, flake-root, ... }:
            flake-parts.lib.mkFlake { inherit inputs; } {
            imports =
                [ inputs.flake-containers.flakeModule inputs.flake-root.flakeModule ];
    
            systems = [ "x86_64-linux" ];
    
            flake-containers = {
                # Enable the containers
                enable = true;
                # Define the containers as nixos modules
                containers = {
                    # One container named httpsserver
                    httpserver = {
                        # Define volumes to be bind inside the conaiter
                        volumes = [ "/tmp" "src:/tmp/src" ];
                        volumes-ro = [ "/data" ];
                        
                        # The configuration is a regular nixos module
                        configuration = { pkgs, lib, ... }: {
                            # Network configuration.
                            networking.useDHCP = false;
                            networking.firewall.allowedTCPPorts = [ 80 ];
    
                            # Enable a web server.
                            services.httpd = {
                                enable = true;
                                adminAddr = "morty@example.org";
                            };
                        };
                    };
                };
            };
        };
    }
  2. Use nix flake show to see what is available. For each container, the flake defines the command to manage.
    > nix flake show
    git+file:///home/adfaure/code/flake-containers?dir=examples/httpserver
    ├───devShells
    │   └───x86_64-linux
    │       └───flake-containers: development environment 'nix-shell'
    └───packages
        └───x86_64-linux
            ├───httpserver-down: package 'httpserver-down'
            ├───httpserver-shell: package 'httpserver-shell'
            └───httpserver-up: package 'httpserver-up'
    
  3. Use nix develop .#flake-containers to dive into a shell containing commands to manage your containers.
  4. Start the container with sudo httpserver-up to start the container.
  5. The container should appear with the machinectl list command.

Similar Projects

Similar (or related) projects Description
nixos-containers Declare and manage NixOs systemd containers.
extra-container Generates systemd service files for starting containers directly from systemctl. Maintains compatibility with nixos-container.
nixos-compose The goal of NixOS-Compose is to reduce the burden of setting up ephemeral distributed systems thanks to Nix functional package manager and Nixos
devenv Use a simple unified configuration to configure packages, processes, services, scripts, git hooks, integrations. Devenv has its own way to create containers.
nix2Container An archive-less dockerTools.buildImage implementation
Arion Run docker-compose with help from Nix/NixOS.

Contributing

Contributions are welcome! Feel free to open issues for bugs or feature requests, and submit pull requests with improvements.

License

This project is licensed under the MIT License.

References

About

A proof of concept project for defining NixOS containers (systemd-nspawn) in a flake.nix file.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published