at 24.11-pre 4.6 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.virtualisation.anbox; 8 9 addrOpts = v: addr: pref: name: { 10 address = mkOption { 11 default = addr; 12 type = types.str; 13 description = '' 14 IPv${toString v} ${name} address. 15 ''; 16 }; 17 18 prefixLength = mkOption { 19 default = pref; 20 type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128)); 21 description = '' 22 Subnet mask of the ${name} address, specified as the number of 23 bits in the prefix (`${if v == 4 then "24" else "64"}`). 24 ''; 25 }; 26 }; 27 28 finalImage = if cfg.imageModifications == "" then cfg.image else ( pkgs.callPackage ( 29 { runCommandNoCC, squashfsTools }: 30 31 runCommandNoCC "${cfg.image.name}-modified.img" { 32 nativeBuildInputs = [ 33 squashfsTools 34 ]; 35 } '' 36 echo "-> Extracting Anbox root image..." 37 unsquashfs -dest rootfs ${cfg.image} 38 39 echo "-> Modifying Anbox root image..." 40 ( 41 cd rootfs 42 ${cfg.imageModifications} 43 ) 44 45 echo "-> Packing modified Anbox root image..." 46 mksquashfs rootfs $out -comp xz -no-xattrs -all-root 47 '' 48 ) { }); 49 50in 51 52{ 53 54 options.virtualisation.anbox = { 55 56 enable = mkEnableOption "Anbox"; 57 58 image = mkOption { 59 default = pkgs.anbox.image; 60 defaultText = literalExpression "pkgs.anbox.image"; 61 type = types.package; 62 description = '' 63 Base android image for Anbox. 64 ''; 65 }; 66 67 imageModifications = mkOption { 68 default = ""; 69 type = types.lines; 70 description = '' 71 Commands to edit the image filesystem. 72 73 This can be used to e.g. bundle a privileged F-Droid. 74 75 Commands are ran with PWD being at the root of the filesystem. 76 ''; 77 }; 78 79 extraInit = mkOption { 80 type = types.lines; 81 default = ""; 82 description = '' 83 Extra shell commands to be run inside the container image during init. 84 ''; 85 }; 86 87 ipv4 = { 88 container = addrOpts 4 "192.168.250.2" 24 "Container"; 89 gateway = addrOpts 4 "192.168.250.1" 24 "Host"; 90 91 dns = mkOption { 92 default = "1.1.1.1"; 93 type = types.str; 94 description = '' 95 Container DNS server. 96 ''; 97 }; 98 }; 99 }; 100 101 config = mkIf cfg.enable { 102 103 assertions = singleton { 104 assertion = with config.boot.kernelPackages; kernelAtLeast "5.5" && kernelOlder "5.18"; 105 message = "Anbox needs a kernel with binder and ashmem support"; 106 }; 107 108 environment.systemPackages = with pkgs; [ anbox ]; 109 110 systemd.mounts = singleton { 111 requiredBy = [ "anbox-container-manager.service" ]; 112 description = "Anbox Binder File System"; 113 what = "binder"; 114 where = "/dev/binderfs"; 115 type = "binder"; 116 }; 117 118 virtualisation.lxc.enable = true; 119 networking.bridges.anbox0.interfaces = []; 120 networking.interfaces.anbox0.ipv4.addresses = [ cfg.ipv4.gateway ]; 121 122 networking.nat = { 123 enable = true; 124 internalInterfaces = [ "anbox0" ]; 125 }; 126 127 # Ensures NetworkManager doesn't touch anbox0 128 networking.networkmanager.unmanaged = [ "anbox0" ]; 129 130 systemd.services.anbox-container-manager = let 131 anboxloc = "/var/lib/anbox"; 132 in { 133 description = "Anbox Container Management Daemon"; 134 135 environment.XDG_RUNTIME_DIR="${anboxloc}"; 136 137 wantedBy = [ "multi-user.target" ]; 138 preStart = let 139 initsh = pkgs.writeText "nixos-init" ('' 140 #!/system/bin/sh 141 setprop nixos.version ${config.system.nixos.version} 142 143 # we don't have radio 144 setprop ro.radio.noril yes 145 stop ril-daemon 146 147 # speed up boot 148 setprop debug.sf.nobootanimation 1 149 '' + cfg.extraInit); 150 initshloc = "${anboxloc}/rootfs-overlay/system/etc/init.goldfish.sh"; 151 in '' 152 mkdir -p ${anboxloc} 153 mkdir -p $(dirname ${initshloc}) 154 [ -f ${initshloc} ] && rm ${initshloc} 155 cp ${initsh} ${initshloc} 156 chown 100000:100000 ${initshloc} 157 chmod +x ${initshloc} 158 ''; 159 160 serviceConfig = { 161 ExecStart = '' 162 ${pkgs.anbox}/bin/anbox container-manager \ 163 --data-path=${anboxloc} \ 164 --android-image=${finalImage} \ 165 --container-network-address=${cfg.ipv4.container.address} \ 166 --container-network-gateway=${cfg.ipv4.gateway.address} \ 167 --container-network-dns-servers=${cfg.ipv4.dns} \ 168 --use-rootfs-overlay \ 169 --privileged \ 170 --daemon 171 ''; 172 }; 173 }; 174 }; 175 176}