NixOS Containers: Difference between revisions

imported>Srid
m Link to https://wiki.archlinux.org/title/systemd-nspawn
Luchs (talk | contribs)
See also: Fix link to nixos-container.pl
 
(23 intermediate revisions by 13 users not shown)
Line 1: Line 1:
== Native NixOS containers ==
Setup native [https://wiki.archlinux.org/title/systemd-nspawn systemd-nspawn] containers, which are running NixOS and are configured and managed by NixOS using the <code>containers</code> directive.


It is possible to configure native [https://wiki.archlinux.org/title/systemd-nspawn systemd-nspawn] containers, which are running NixOS and are configured and managed by NixOS using the <code>containers</code> directive.
See [[Docker]] page for OCI container (Docker, Podman) configuration.


=== Installation ===
=== Configuration ===


The following example creates a container called <code>nextcloud</code> running the web application [[Nextcloud]]. It will start automatically at boot and has its private network subnet.
The following example creates a container called webserver running a httpd web server. It will start automatically at boot and has its private network subnet.


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
Line 16: Line 16:
};
};


containers.nextcloud = {
containers.webserver = {
   autoStart = true;              
   autoStart = true;
   privateNetwork = true;          
   privateNetwork = true;
   hostAddress = "192.168.100.10";
   hostAddress = "192.168.100.10";
   localAddress = "192.168.100.11";
   localAddress = "192.168.100.11";
   hostAddress6 = "fc00::1";
   hostAddress6 = "fc00::1";
   localAddress6 = "fc00::2";
   localAddress6 = "fc00::2";
   config = { config, pkgs, ... }: {
   config = { config, pkgs, lib, ... }: {


     services.nextcloud = {                    
     services.httpd = {
       enable = true;                  
       enable = true;
       package = pkgs.nextcloud24;
       adminAddr = "admin@example.org";
      hostName = "localhost";
      config.adminpassFile = "${pkgs.writeText "adminpass" "test123"}"; # DON'T DO THIS IN PRODUCTION - the password file will be world-readable in the Nix Store!
     };
     };


     system.stateVersion = "22.05";
     networking = {
      firewall.allowedTCPPorts = [ 80 ];


    networking.firewall = {
      # Use systemd-resolved inside the container
       enable = true;
       # Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
       allowedTCPPorts = [ 80 ];
       useHostResolvConf = lib.mkForce false;
     };
     };
   
    services.resolved.enable = true;


     # Manually configure nameserver. Using resolved inside the container seems to fail
     system.stateVersion = "24.11";
    # currently
    environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
 
   };
   };
};
};
</nowiki>}}
</nowiki>}}


In order to reach the web application on the host system, we have to open [[Firewall]] port 80 and also configure NAT through <code>networking.nat</code>. The web service of the container will be available at http://192.168.100.10
In order to reach the web application on the host system, we have to open [[Firewall]] port 80 and also configure NAT through <code>networking.nat</code>. The web service of the container will be available at http://192.168.100.11
 
==== Networking ====
 
{{expansion}}
 
By default, if <code>privateNetwork</code> is not set, the container shares the network with the host, enabling it to bind any port on any interface. However, when <code>privateNetwork</code> is set to <code>true</code>, the container gains its private virtual <code>eth0</code> and <code>ve-<container_name></code> on the host. This isolation is beneficial when you want the container to have its dedicated networking stack.
 
'''NAT (Network Address Translation)'''
 
<syntaxhighlight lang="nix">
</syntaxhighlight>
 
'''Bridge'''
 
<syntaxhighlight lang="nix">
networking = {
  bridges.br0.interfaces = [ "eth0s31f6" ]; # Adjust interface accordingly
 
  # Get bridge-ip with DHCP
  useDHCP = false;
  interfaces."br0".useDHCP = true;
 
  # Set bridge-ip static
  interfaces."br0".ipv4.addresses = [{
    address = "192.168.100.3";
    prefixLength = 24;
  }];
  defaultGateway = "192.168.100.1";
  nameservers = [ "192.168.100.1" ];
};
 
containers.<name> = {
  privateNetwork = true;
  hostBridge = "br0"; # Specify the bridge name
  localAddress = "192.168.100.5/24";
  config = { };
};
</syntaxhighlight>


=== Usage ===
=== Usage ===
List containers
<syntaxhighlight lang="console">
# machinectl list
</syntaxhighlight>


Checking the status of the container
Checking the status of the container
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
# systemctl status container@nextcloud
# systemctl status container@webserver
</syntaxhighlight>
</syntaxhighlight>


Login into the container
Login into the container
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
# nixos-container root-login nextcloud
# nixos-container root-login webserver
</syntaxhighlight>
</syntaxhighlight>


Start or stop a container
Start or stop a container
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
# nixos-container start nextcloud
# nixos-container start webserver
# nixos-container stop nextcloud
# nixos-container stop webserver
</syntaxhighlight>
</syntaxhighlight>


Destroy a container including its file system
Destroy a container including its file system
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
# nixos-container destroy nextcloud
# nixos-container destroy webserver
</syntaxhighlight>
</syntaxhighlight>


Further informations are available in the {{manual:nixos|sec=#ch-containers|chapter=NixOS manual}}.
View log for container<syntaxhighlight lang="console">
# journalctl -M webserver
</syntaxhighlight>Further informations are available in the {{manual:nixos|sec=#ch-containers|chapter=NixOS manual}}.


=== Troubleshooting ===
== Tips and tricks ==


Configuring nameservers for containers is [https://github.com/NixOS/nixpkgs/issues/162686 currently broken]. Therefore in some cases internet connectivity can be broken inside the containers. A temporary workaround is to manually write the <code>/etc/nixos/resolv.conf</code> file like this:
==== Define and create nixos-container from a Flake file ====
We can define and create a custom container called <code>container</code> from a file stored as <code>flake.nix</code>. In this case we use the unstable branch of the nixpkgs repository as a source.<syntaxhighlight lang="nix">
{
  inputs.nixpkgs.url = "nixpkgs/nixos-unstable";


{{file|/etc/nixos/configuration.nix|nix|<nowiki>
  outputs = { self, nixpkgs }: {
containers.nextcloud.config = { config, pkgs, ... }: {
 
  [...]
    nixosConfigurations.container = nixpkgs.lib.nixosSystem {
  environment.etc."resolv.conf".text = "nameserver 8.8.8.8";
      system = "x86_64-linux";
};
      modules =
</nowiki>}}
        [ ({ pkgs, ... }: {
            boot.isContainer = true;


== Declarative docker containers ==
            networking.firewall.allowedTCPPorts = [ 80 ];


Example config:
            services.httpd = {
  { config, pkgs, ... }:
              enable = true;
  {
              adminAddr = "morty@example.org";
    config.virtualisation.oci-containers.containers = {
            };
      hackagecompare = {
           })
        image = "chrissound/hackagecomparestats-webserver:latest";
        ports = ["127.0.0.1:3010:3010"];
        volumes = [
          "/root/hackagecompare/packageStatistics.json:/root/hackagecompare/packageStatistics.json"
        ];
        cmd = [
           "--base-url"
          "\"/hackagecompare\""
         ];
         ];
    };
  };
}
</syntaxhighlight>To create and run that container, enter following commands. In this example the <code>flake.nix</code> file is in the same directory.<syntaxhighlight lang="console">
# nixos-container create flake-test --flake .
host IP is 10.233.4.1, container IP is 10.233.4.2
# nixos-container start flake-test
</syntaxhighlight>
==== Use agenix secrets in container ====
To add <code>agenix</code> secrets to a container bind mount the <code>ssh-host.key</code> and import the <code>agenix.nixosModule</code> and set <code>age.identityPaths</code> [https://discourse.nixos.org/t/secrets-inside-nixos-containers/34403/6 Source]<syntaxhighlight lang="nix">
{ agenix, ... }:
{
  containers."withSecret" = {
    # pass the private key to the container for agenix to decrypt the secret
    bindMounts."/etc/ssh/ssh_host_ed25519_key".isReadOnly = true;
    config =
      {
        config,
        lib,
        pkgs,
        ...
      }:
      {
        imports = [ agenix.nixosModules.default ]; # import agenix-module into the nixos-container
        age.identityPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; # isn't set automatically when openssh is not setup
        # import the secret
        age.secrets."secret-name" = {
          file = ../secrets/secret.age;
        };
       };
       };
    };
  };
  }
}
</syntaxhighlight>


== Troubleshooting ==
== Troubleshooting ==


=== I have changed the host's channel and some services are no longer functional ===
==== I have changed the host's channel and some services are no longer functional ====
 
'''Symptoms:'''
'''Symptoms:'''
* Lost data in PostgreSQL database
* Lost data in PostgreSQL database
Line 122: Line 197:
* [https://blog.beardhatcode.be/2020/12/Declarative-Nixos-Containers.html Blog Article - Declarative NixOS Containers]
* [https://blog.beardhatcode.be/2020/12/Declarative-Nixos-Containers.html Blog Article - Declarative NixOS Containers]
* [https://discourse.nixos.org/t/extra-container-run-declarative-containers-without-full-system-rebuilds/511 NixOS Discourse - Extra-container: Run declarative containers without full system rebuilds]
* [https://discourse.nixos.org/t/extra-container-run-declarative-containers-without-full-system-rebuilds/511 NixOS Discourse - Extra-container: Run declarative containers without full system rebuilds]
* [https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/virtualization/nixos-container/nixos-container.pl Nixpkgs - nixos-container.pl]
* [https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/ni/nixos-container/nixos-container.pl Nixpkgs - nixos-container.pl]
* [https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/nixos-containers.nix Nixpkgs - nixos-containers.nix]
* [https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/nixos-containers.nix Nixpkgs - nixos-containers.nix]
 
* [https://nixcademy.com/2023/08/29/nixos-nspawn/ nixos-nspawn]
* [https://github.com/tfc/nspawn-nixos tfc/nspawn-nixos]
* MicroVMs as a more isolated alternative, e.g. with https://github.com/astro/microvm.nix
[[Category:Server]]
[[Category:Server]]
[[Category:NixOS]]
[[Category:NixOS]]
[[Category:Container]]