Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support declarative container options in imperative setup #18355

Open
danbst opened this issue Sep 6, 2016 · 21 comments
Open

Support declarative container options in imperative setup #18355

danbst opened this issue Sep 6, 2016 · 21 comments
Labels
2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md

Comments

@danbst
Copy link
Contributor

danbst commented Sep 6, 2016

It is now impossible to set bind mounts for imperative containers. I don't whether it is by design, or there is no interface to do it imperatively yet. I hope for latter. In that case we can have this container config:

{ config, pkgs, lib, ...}:
{
   services.postgresql.enable = true;
   services.postgresql.dataDir = "/media/db";
   deployment.container.bindMounts = [{ "/media/db" = { hostPath = "/media/db"; isReadOnly = false; }; }];
   deployment.container.privateNetwork = true;
}

Main use case is to improve usability of container deployments in NixOps. Another usecase it to simplify solution for problem in #17365 (if I understood the problem correctly).

@groxxda
Copy link
Contributor

groxxda commented Sep 6, 2016

Imperative bind mounts should be possible via machinectl bind <machine> <hostpath> [<containerpath>] optionally with --mkdir to create the path inside the container.

I doubt they persist across reboots but have not tested.

If you are looking for a declarative way, this works:

containers.<machine>.bindMounts."<containerpath>".hostPath = "<hostpath>";

@johbo
Copy link
Contributor

johbo commented Mar 24, 2017

Came around this problem while trying to deploy containers via NixOPS. I've done some early experiments.

Declarative containers are currently quite powerful compared to the imperative approach and that's a pity, since NixOPS' container backend is based on the imperative approach via the tool nixos-container.

From researching how containers are actually implemented, I've found that declarative containers take advantage of custom unit files for some settings and they use mode values in the container's configuration file. These values are then used in the startup files of the container.

Imperative containers have way less options for configuration. They use a template unit file based on an empty dummy configuration and the container's configuration file is written by nixos-container instead of being built via Nix.

By manually tweaking the configuration file of my test containers in /etc/containers/ some of the features from declarative containers can be used. They are just not accessible via nixos-container, still they work. That's because the startup scripts of the containers base most of their decisions on this configuration file.

Most of the fragments are defined in this module: https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/containers.nix

Based on my current understanding I think that there might be a chance to actually adjust the way how containers are configured, so that the deployment options sit inside of the container definition, like you suggest above. In my experiments I've used a different namespace config.container instead of deployment.container just because the deployment namespace seems to be more related to nixops. I might be wrong here though.

The idea is to move all options of the declarative containers from containers.<name>.* into containers.<name>.config.* so that they would reside inside the container's configuration. This way we could also use them in NixOPS and probably also for imperative containers based on a configuration file via nixos-container.

Currently I am thinking that the container's configuration file (or in the imperative case the base of it) should be build by nix and maybe added as a symlink into the system derivation, so that nixos-container could use it from there and the user could inspect it via the system profile. I am not sure if that's having unwanted side effects though, first time I am touching this area.

It would probably also be possible to support adjusted startup scripts based on the same logic which is used for declarative containers. The tricky part would be to tell the template unit file, that we want a specific startup script or snippet to be executed. This might be doable based on a new variable in the container's configuration file, so that the unit template of the host would find the script.

I've made an experiment which demonstrates parts of the idea. Would be great to get some feedback if that's a reasonable direction. For simplicity I've put the code into my nixops fork into this branch: https://github.com/johbo/nixops/tree/exp-containers

The compare view can be found here: https://github.com/NixOS/nixops/compare/master...johbo:exp-containers?expand=1

The following is an example how I've used it in my small test scenario:

  cont1 = { config, pkgs, ... }: {
    # NixOPS specific
    deployment.targetEnv = "container";
    deployment.container.host = "nixvm1";

    # This would also work in NixOS, needs a tweaked nixos-container script though.
    container = {
      writeContainerConfig = true;
      privateNetwork = true;
      localAddress = "10.233.0.2";
      hostAddress = "10.233.0.1";
      hostBridge = "br0";
    };
  };

@danbst
Copy link
Contributor Author

danbst commented Mar 27, 2017

Looking forward for Nixos side implementation! Why did you go nixops side?

@boxofrox
Copy link
Contributor

I stumbled upon this while trying to learn how to define bind mounts in an imperative container. I tried looking at @johbo's commits, but I'm new to Nix and it's all gibberish to me at this point.

I want to mention a concern that @johbo's commits may or may not take into account (if it even should). I noticed that I'm editing settings for my imperative container in /var/lib/containers/<name>/etc/nixos/configuration.nix, and this file appears to be inside the container. If bindMounts and such are specified in this config file, is there no concern that a compromised container might edit the configuration.nix, change the bindMounts, and trigger a restart of the container by killing all processes, and gain access to portions of the filesystem that should never have been accessible?

Declarative containers, on the other hand, do not have a /var/lib/containers/<name>/etc/nixos/configuration.nix, AFAICT, and if the settings aren't exposed inside the container in a writable fashion, I find this preferable.

Perhaps dropping privileges inside the container is sufficient (I still need to determine how this is achieved), or perhaps Nix is so awesome it already handles this, but if configuring bindMounts inside a container is the direction this solution is heading, consider moving the configuration.nix outside the container (or lock down writes even from root) as you move forward.

@danbst
Copy link
Contributor Author

danbst commented Apr 15, 2017

Currently it is clearly stated that compromised root in container can get access to root in host, but your concern is a valid one

@nh2
Copy link
Contributor

nh2 commented Dec 10, 2017

I need this too, because I need to override DeviceAllow for my nixops containers. See NixOS/nixops#802

@danbst
Copy link
Contributor Author

danbst commented Mar 2, 2019

My usecase is finally possible with https://github.com/erikarvstedt/extra-container

Next issue should be intergrate extra-container into nixos-container.

@danbst danbst closed this as completed Mar 2, 2019
@nh2
Copy link
Contributor

nh2 commented Mar 2, 2019

@danbst Did you inted to close this? It seems like until

intergrate extra-container into nixos-container

is done, this problem continues to exist.

(Tentatively reopening)

@nh2 nh2 reopened this Mar 2, 2019
@danbst
Copy link
Contributor Author

danbst commented Mar 2, 2019

yep, I wanted to close this issue. Actually, I think integrating extra-container stuff into nixos-container isn't trivial, maybe better would be to design nixos container command from scratch (#54188), however that isn't trivial as well =)

@nh2
Copy link
Contributor

nh2 commented Mar 3, 2019

integrating extra-container stuff into nixos-container isn't trivial, maybe better would be to design nixos container command from scratch (#54188), however that isn't trivial as well =)

@danbst That all sounds reasonable, but shouldn't we keep the ticket open then, as there is no current general solution?

@danbst
Copy link
Contributor Author

danbst commented Mar 3, 2019

@nh2 alright. I wonder if there are drawbacks of using deployment.container.* option inside container config versus containers.* outside container config (apart from implementation complications).

@ghost
Copy link

ghost commented Sep 3, 2019

Nix is now, with flakes, going towards splitting code up. Merging everything in nixpkgs isn't the way to go anymore. Containers are, in all likelyhood, better as a separate flake. We can go the other way, and take stuff out of nixpkgs.

@stale
Copy link

stale bot commented Jun 2, 2020

Thank you for your contributions.
This has been automatically marked as stale because it has had no activity for 180 days.
If this is still important to you, we ask that you leave a comment below. Your comment can be as simple as "still important to me". This lets people see that at least one person still cares about this. Someone will have to do this at most twice a year if there is no other activity.
Here are suggestions that might help resolve this more quickly:

  1. Search for maintainers and people that previously touched the
    related code and @ mention them in a comment.
  2. Ask on the NixOS Discourse. 3. Ask on the #nixos channel on
    irc.freenode.net.

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jun 2, 2020
@nh2
Copy link
Contributor

nh2 commented Jun 2, 2020

still important to me

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jun 2, 2020
@stale
Copy link

stale bot commented Nov 29, 2020

I marked this as stale due to inactivity. → More info

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Nov 29, 2020
@aanderse
Copy link
Member

I wonder what @erikarvstedt has to say on this topic...

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Nov 29, 2020
@stale
Copy link

stale bot commented Jun 3, 2021

I marked this as stale due to inactivity. → More info

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Jun 3, 2021
@andrevmatos
Copy link
Member

also interested in this, specially with flakes

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Aug 7, 2021
@stale
Copy link

stale bot commented Apr 29, 2022

I marked this as stale due to inactivity. → More info

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Apr 29, 2022
@ranfdev
Copy link
Contributor

ranfdev commented May 15, 2022

Still interested, for containers defined inside flakes

@stale stale bot removed the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label May 15, 2022
@ranfdev
Copy link
Contributor

ranfdev commented May 15, 2022

It's worth taking a look at microvm, which is setting up vm options as nixos modules:

outputs = { self, nixpkgs, microvm }: {
    # Example nixosConfigurations entry
    nixosConfigurations.my-microvm = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        # Include the microvm module
        microvm.nixosModules.microvm
        # Add more modules here
        {
          networking.hostName = "my-microvm";
          microvm.hypervisor = "cloud-hypervisor";
        }
      ];
    };
  };

It should be possible to create a module defining container options, to be put inside the container definition, as microvm is doing

@stale stale bot added the 2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md label Nov 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2.status: stale https://github.com/NixOS/nixpkgs/blob/master/.github/STALE-BOT.md
Projects
None yet
Development

No branches or pull requests

8 participants