NixOS containers shared network

Hello everyone,

i would like to deploy Gitea on NixOS as an unprivileged container using the “virtualisation.oci-containers.containers” configuration option and podman as the backend.
But how can i share a network between the database and webserver container without using the host network, just like in docker compose?

My current config looks like this:

boot.kernel.sysctl = {
  "net.ipv4.ip_unprivileged_port_start" = 80;
};

networking.firewall = {
  enable = true;
  allowedTCPPorts = [ 80 2222 ];
};

virtualisation = {
  containers.enable = true;
  podman = {
    enable = true;
    dockerCompat = true;
    defaultNetwork.settings.dns_enabled = true;
  };
};

users.users.gitea = {
  isNormalUser = true;
  extraGroups = [ "podman" ];
};

virtualisation.oci-containers.backend = "podman";
virtualisation.oci-containers.containers = {
  gitea = {
    image = "docker.gitea.com/gitea:1.23.8-rootless";
    podman.user = "gitea";
    autoStart = true;
    ports = [ "80:3000" "2222:2222" ];
    volumes = [ 
      "data:/var/lib/gitea"
      "config:/etc/gitea"
      "/etc/localtime:/etc/localtime:ro"
    ];
    environment = {
      GITEA__database__DB_TYPE="postgres";
      GITEA__database__HOST="db:5432";
      GITEA__database__NAME="gitea";
      GITEA__database__USER="gitea";
      GITEA__database__PASSWD="gitea";
    };

    dependsOn = [ "db" ];
  };

  db = {
    image = "docker.io/library/postgres:14";
    podman.user = "gitea";
    autoStart = true;
    environment = {
      POSTGRES_USER="gitea";
      POSTGRES_PASSWORD="gitea";
      POSTGRES_DB="gitea";
    };
    volumes = [ 
      "postgres:/var/lib/postgresql/data"
    ];
  };
};

Does anyone has a tip?

i finally found the solution, this is my working config:

{ config, pkgs, modulesPath, ... }: 

let
  podman = pkgs.podman;
in
{
  users.groups.gitea = {};

  users.users.gitea = {
    isSystemUser = true;
    uid = 995;
    createHome = true;
    home = "/var/gitea";
    linger = true;
    shell = pkgs.bash;    
    group = "gitea";
    autoSubUidGidRange = true;
    extraGroups = [ "podman" ];
  };

  systemd.tmpfiles.rules = [
    # Clean up rootless podman temp storage on boot to prevent boot ID mismatch
    "R /tmp/storage-run-995 - - - -"
  ];

  boot.kernel.sysctl = {
    "net.ipv4.ip_unprivileged_port_start" = 80;
  };

  networking.firewall = {
    enable = true;
    allowedTCPPorts = [ 80 2222 ];
  };

  virtualisation = {
    containers.enable = true;
    podman = {
      autoPrune.enable = true;
      enable = true;
      dockerCompat = true;
      defaultNetwork.settings.dns_enabled = true;
    };
  };

  systemd.services."podman-network-gitea" = {
    description = "Create gitea network for rootless podman";
    wantedBy = [ "multi-user.target" ];
    before = [ "podman-db.service" "podman-gitea.service" ];

    after = [ "user@995.service" ];
    requires = [ "user@995.service" ];

    serviceConfig = {
      Type = "oneshot";
      RemainAfterExit = true;
      User = "gitea";
      Group = "gitea";
      Environment = [
        "XDG_RUNTIME_DIR=/run/user/995"
        "PATH=/run/wrappers/bin:${pkgs.lib.makeBinPath [ pkgs.podman ]}"
      ];
    };

    script = ''
      if ! ${podman}/bin/podman network exists gitea; then
        ${podman}/bin/podman network create gitea
      fi
    '';
  };

  systemd.services.podman-db = {
    after = [ "user@995.service" "podman-network-gitea.service" ];
    requires = [ "user@995.service" "podman-network-gitea.service" ];
    serviceConfig = {
      RemainAfterExit = true;
      Environment = [ "XDG_RUNTIME_DIR=/run/user/995" ];
    };
  };

  systemd.services.podman-gitea = {
    after = [ "user@995.service" "podman-network-gitea.service" ];
    requires = [ "user@995.service" "podman-network-gitea.service" ];
    serviceConfig = {
      RemainAfterExit = true;
      Environment = [ "XDG_RUNTIME_DIR=/run/user/995" ];
    };
  };

  virtualisation.oci-containers.backend = "podman";
  virtualisation.oci-containers.containers = {
    gitea = {
      image = "docker.gitea.com/gitea:1.23.8-rootless";
      podman.user = "gitea";
      autoStart = true;
      ports = [ "80:3000" "2222:2222" ];
      volumes = [
        "gitea-data:/var/lib/gitea"
        "gitea-config:/etc/gitea"
        "/etc/localtime:/etc/localtime:ro"
      ];

      networks = [
        "gitea"
      ];

      environment = {
        GITEA__database__DB_TYPE="postgres";
        GITEA__database__HOST="db:5432";
        GITEA__database__NAME="gitea";
        GITEA__database__USER="gitea";
        GITEA__database__PASSWD="gitea";
      };

      dependsOn = [ "db" ];
      extraOptions = [
        "--network-alias=gitea"
      ];
    };

    db = {
      image = "docker.io/library/postgres:14";
      podman.user = "gitea";
      autoStart = true;
      volumes = [
        "postgres-data:/var/lib/postgresql/data"
      ];
      networks = [
        "gitea"
      ];
      environment = {
        POSTGRES_USER="gitea";
        POSTGRES_PASSWORD="gitea";
        POSTGRES_DB="gitea";
        PGDATA = "/var/lib/postgresql/data/pgdata";
      };
      extraOptions = [
        "--network-alias=db"
      ];
    };
  };
}

With podman you could as well run everything inside a pod and use localhost to access the services from within the pod. But you would need to use a systemd one shot to create that as well.