diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 91645a57b496..0f3c9d0c5627 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -876,6 +876,7 @@ ./tasks/trackpoint.nix ./tasks/powertop.nix ./testing/service-runner.nix + ./virtualisation/anbox.nix ./virtualisation/container-config.nix ./virtualisation/containers.nix ./virtualisation/docker.nix diff --git a/nixos/modules/virtualisation/anbox.nix b/nixos/modules/virtualisation/anbox.nix new file mode 100644 index 000000000000..9cb89e7b2926 --- /dev/null +++ b/nixos/modules/virtualisation/anbox.nix @@ -0,0 +1,144 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.virtualisation.anbox; + kernelPackages = config.boot.kernelPackages; + addrOpts = v: addr: pref: name: { + address = mkOption { + default = addr; + type = types.str; + description = '' + IPv${toString v} ${name} address. + ''; + }; + + prefixLength = mkOption { + default = pref; + type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128)); + description = '' + Subnet mask of the ${name} address, specified as the number of + bits in the prefix (${if v == 4 then "24" else "64"}). + ''; + }; + }; + +in + +{ + + options.virtualisation.anbox = { + + enable = mkEnableOption "Anbox"; + + image = mkOption { + default = pkgs.anbox.image; + example = literalExample "pkgs.anbox.image"; + type = types.package; + description = '' + Base android image for Anbox. + ''; + }; + + extraInit = mkOption { + type = types.lines; + default = ""; + description = '' + Extra shell commands to be run inside the container image during init. + ''; + }; + + ipv4 = { + container = addrOpts 4 "192.168.250.2" 24 "Container"; + gateway = addrOpts 4 "192.168.250.1" 24 "Host"; + + dns = mkOption { + default = "1.1.1.1"; + type = types.string; + description = '' + Container DNS server. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + + assertions = singleton { + assertion = versionAtLeast (getVersion config.boot.kernelPackages.kernel) "4.18"; + message = "Anbox needs user namespace support to work properly"; + }; + + environment.systemPackages = with pkgs; [ anbox ]; + + boot.kernelModules = [ "ashmem_linux" "binder_linux" ]; + boot.extraModulePackages = [ kernelPackages.anbox ]; + + services.udev.extraRules = '' + KERNEL=="ashmem", NAME="%k", MODE="0666" + KERNEL=="binder*", NAME="%k", MODE="0666" + ''; + + virtualisation.lxc.enable = true; + networking.bridges.anbox0.interfaces = []; + networking.interfaces.anbox0.ipv4.addresses = [ cfg.ipv4.gateway ]; + + networking.nat = { + enable = true; + internalInterfaces = [ "anbox0" ]; + }; + + systemd.services.anbox-container-manager = let + anboxloc = "/var/lib/anbox"; + in { + description = "Anbox Container Management Daemon"; + + environment.XDG_RUNTIME_DIR="${anboxloc}"; + + wantedBy = [ "multi-user.target" ]; + after = [ "systemd-udev-settle.service" ]; + preStart = let + initsh = let + ip = cfg.ipv4.container.address; + gw = cfg.ipv4.gateway.address; + dns = cfg.ipv4.dns; + in + pkgs.writeText "nixos-init" ('' + #!/system/bin/sh + setprop nixos.version ${config.system.nixos.version} + + # we don't have radio + setprop ro.radio.noril yes + stop ril-daemon + + # speed up boot + setprop debug.sf.nobootanimation 1 + '' + cfg.extraInit); + initshloc = "${anboxloc}/rootfs-overlay/system/etc/init.goldfish.sh"; + in '' + mkdir -p ${anboxloc} + mkdir -p $(dirname ${initshloc}) + [ -f ${initshloc} ] && rm ${initshloc} + cp ${initsh} ${initshloc} + chown 100000:100000 ${initshloc} + chmod +x ${initshloc} + ''; + + serviceConfig = { + ExecStart = '' + ${pkgs.anbox}/bin/anbox container-manager \ + --data-path=${anboxloc} \ + --android-image=${cfg.image} \ + --container-network-address=${cfg.ipv4.container.address} \ + --container-network-gateway=${cfg.ipv4.gateway.address} \ + --container-network-dns-servers=${cfg.ipv4.dns} \ + --use-rootfs-overlay \ + --privileged + ''; + }; + }; + }; + +} diff --git a/pkgs/development/libraries/properties-cpp/default.nix b/pkgs/development/libraries/properties-cpp/default.nix new file mode 100644 index 000000000000..06444e776703 --- /dev/null +++ b/pkgs/development/libraries/properties-cpp/default.nix @@ -0,0 +1,27 @@ +{ stdenv, lib, fetchurl, cmake, pkgconfig, gtest, doxygen +, graphviz, lcov, writeText }: + +stdenv.mkDerivation rec { + pname = "properties-cpp"; + version = "0.0.1"; + + src = let srcver = version+"+14.10.20140730"; in + fetchurl { + url = "https://launchpad.net/ubuntu/+archive/primary/+files/${pname}_${srcver}.orig.tar.gz"; + sha256 = "08vjyv7ibn6jh2ikj5v48kjpr3n6hlkp9qlvdn8r0vpiwzah0m2w"; + }; + + buildInputs = [ cmake gtest doxygen pkgconfig graphviz lcov ]; + + patchPhase = '' + sed -i "/add_subdirectory(tests)/d" CMakeLists.txt + ''; + + meta = with stdenv.lib; { + homepage = https://launchpad.net/properties-cpp; + description = "A very simple convenience library for handling properties and signals in C++11."; + license = licenses.lgpl3; + maintainers = with maintainers; [ edwtjo ]; + }; + +} diff --git a/pkgs/os-specific/linux/anbox/default.nix b/pkgs/os-specific/linux/anbox/default.nix new file mode 100644 index 000000000000..bd85b6620ba6 --- /dev/null +++ b/pkgs/os-specific/linux/anbox/default.nix @@ -0,0 +1,127 @@ +{ stdenv, lib, fetchFromGitHub, fetchurl +, cmake, pkgconfig, dbus, makeWrapper +, gtest +, boost +, libcap +, systemd +, mesa +, libGL +, libglvnd +, glib +, git +, SDL2 +, SDL2_image +, properties-cpp +, protobuf +, protobufc +, python +, lxc +}: + +stdenv.mkDerivation rec { + pname = "anbox"; + version = "2019-03-07"; + + src = fetchFromGitHub { + owner = pname; + repo = pname; + rev = "d521e282965462e82465045ab95d4ae1c4619685"; + sha256 = "1wfx4bsyxvrjl16dq5pqgial8rnnsnxzbak2ap0waddz847czxwz"; + }; + + buildInputs = [ + cmake pkgconfig dbus boost libcap gtest systemd mesa glib + SDL2 SDL2_image protobuf protobufc properties-cpp lxc python + makeWrapper libGL + ]; + + patchPhase = '' + patchShebangs scripts + + cat >cmake/FindGMock.cmake <<'EOF' + add_library(gtest INTERFACE) + target_include_directories(gtest INTERFACE ${gtest.dev}/include) + target_link_libraries(gtest INTERFACE ${gtest}/lib/libgtest.so ''${CMAKE_THREAD_LIBS_INIT}) + add_dependencies(gtest GMock) + + add_library(gtest_main INTERFACE) + target_include_directories(gtest_main INTERFACE ${gtest.dev}/include) + target_link_libraries(gtest_main INTERFACE ${gtest}/lib/libgtest_main.so gtest) + + add_library(gmock INTERFACE) + target_include_directories(gmock INTERFACE ${gtest.dev}/include) + target_link_libraries(gmock INTERFACE ${gtest}/lib/libgmock.so gtest) + + add_library(gmock_main INTERFACE) + target_include_directories(gmock_main INTERFACE ${gtest.dev}/include) + target_link_libraries(gmock_main INTERFACE ${gtest}/lib/libgmock_main.so gmock gtest_main) + + set(GTEST_LIBRARIES gtest) + set(GTEST_MAIN_LIBRARIES gtest_main) + set(GMOCK_LIBRARIES gmock gmock_main) + set(GTEST_BOTH_LIBRARIES ''${GTEST_LIBRARIES} ''${GTEST_MAIN_LIBRARIES}) + EOF + ''; + + postInstall = '' + wrapProgram $out/bin/anbox \ + --prefix LD_LIBRARY_PATH : ${stdenv.lib.makeLibraryPath [libGL libglvnd]} \ + --prefix PATH : ${git}/bin + + mkdir -p $out/share/dbus-1/services/ + cat < $out/share/dbus-1/services/org.anbox.service + [D-BUS Service] + Name=org.anbox + Exec=$out/libexec/anbox-session-manager + END + + mkdir $out/libexec + cat > $out/libexec/anbox-session-manager < $out/bin/anbox-application-manager <