Router port sharing not working to container with bridge

Hello,

I try to make a container’s nginx server available over the internet (my domain/public IP).

I use NixOS containers and a bridge network, so each container has its own IP address in the local network. For testing I spin up a nginx on the container and the host.

  • In the local network I can access the host and the container from my PC
    $ curl http://192.168.1.10 # Host local IP
      <html><body>It works: Host</body></html>
    $ curl http://192.168.1.11 # Container local IP
      <html><body>It works: Container</body></html>
    
  • On the router, I now share ports 80 and 443 with the container IP, but it does not work.
    $ curl http://xxx.xxx.xxx.xx --verbose # Public IP
      *   Trying xxx.xxx.xxx.xx:80...
      * connect to xxx.xxx.xxx.xx port 80 from 192.168.1.80 port 46042 failed: Connection timed out
      * Failed to connect to xxx.xxx.xxx.xx port 80 after 133233 ms: Could not connect to server
      * closing connection #0
      curl: (28) Failed to connect to xxx.xxx.xxx.xx port 80 after 133233 ms: Could not connect to server
    
  • When I share the ports with the host IP, it works though.
    $ curl http://xxx.xxx.xxx.xx # Public IP
      <html><body>It works: Host</body></html>
    

Config:

{lib, pkgs, ...}:
{
  system.stateVersion = "24.11";
  networking = {
    hostName = "Host";
    hostId = "bad52g46";
    useDHCP = false;
    enableIPv6 = false;
    defaultGateway = "192.168.1.2";
    nameservers = [
      "192.168.1.2"
      "8.8.8.8"
    ];
    bridges."br0".interfaces = ["enp1s0"];
    interfaces = {
      "br0".ipv4.addresses = [
        {
          address = "192.168.1.10";
          prefixLength = 24;
        }
      ];
    };
    firewall.allowedTCPPorts = [80];
  };

  services.nginx = {
    enable = true;
    virtualHosts.localhost = {
      default = true;
      locations."/" = {
        return = "200 '<html><body>It works: Host</body></html>'";
        extraConfig = ''
          default_type text/html;
        '';
      };
    };
  };

  containers = {
    container1 = {
      autoStart = true;
      privateNetwork = true;
      hostBridge = "br0";
      localAddress = "192.168.1.11/24";

      config = {
        pkgs,
        lib,
        ...
      }: {
        system.stateVersion = "24.11";

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

        services.nginx = {
          enable = true;
          virtualHosts.localhost = {
            default = true;
            locations."/" = {
              return = "200 '<html><body>It works: Container</body></html>'";
              extraConfig = ''
                default_type text/html;
              '';
            };
          };
        };
      };
    };
  };
}

Thanks for your help in advance.

Okay, I solved my problem.

The container actually could not ping 8.8.8.8, so had no internet.

I changed the container networking block to this. Now everything works.

networking = {
  enableIPv6 = false;
  defaultGateway = "192.168.1.2";
  nameservers = [
    "192.168.1.2"
    "8.8.8.8"
  ];
  firewall.allowedTCPPorts = [80];
};

I also removed the previous workaround from the Wiki - NixOS Containers, as it seems to work without.

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