1 { config, lib, pkgs, ... }:
7 cfg = config.virtualisation.anbox;
9 addrOpts = v: addr: pref: name: {
14 IPv${toString v} ${name} address.
18 prefixLength = mkOption {
20 type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128));
22 Subnet mask of the ${name} address, specified as the number of
23 bits in the prefix (`${if v == 4 then "24" else "64"}`).
28 finalImage = if cfg.imageModifications == "" then cfg.image else ( pkgs.callPackage (
29 { runCommandNoCC, squashfsTools }:
31 runCommandNoCC "${cfg.image.name}-modified.img" {
36 echo "-> Extracting Anbox root image..."
37 unsquashfs -dest rootfs ${cfg.image}
39 echo "-> Modifying Anbox root image..."
42 ${cfg.imageModifications}
45 echo "-> Packing modified Anbox root image..."
46 mksquashfs rootfs $out -comp xz -no-xattrs -all-root
54 options.virtualisation.anbox = {
56 enable = mkEnableOption "Anbox";
59 default = pkgs.anbox.image;
60 defaultText = literalExpression "pkgs.anbox.image";
63 Base android image for Anbox.
67 imageModifications = mkOption {
71 Commands to edit the image filesystem.
73 This can be used to e.g. bundle a privileged F-Droid.
75 Commands are ran with PWD being at the root of the filesystem.
79 extraInit = mkOption {
83 Extra shell commands to be run inside the container image during init.
88 container = addrOpts 4 "192.168.250.2" 24 "Container";
89 gateway = addrOpts 4 "192.168.250.1" 24 "Host";
101 config = mkIf cfg.enable {
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";
108 environment.systemPackages = with pkgs; [ anbox ];
110 systemd.mounts = singleton {
111 requiredBy = [ "anbox-container-manager.service" ];
112 description = "Anbox Binder File System";
114 where = "/dev/binderfs";
118 virtualisation.lxc.enable = true;
119 networking.bridges.anbox0.interfaces = [];
120 networking.interfaces.anbox0.ipv4.addresses = [ cfg.ipv4.gateway ];
124 internalInterfaces = [ "anbox0" ];
127 # Ensures NetworkManager doesn't touch anbox0
128 networking.networkmanager.unmanaged = [ "anbox0" ];
130 systemd.services.anbox-container-manager = let
131 anboxloc = "/var/lib/anbox";
133 description = "Anbox Container Management Daemon";
135 environment.XDG_RUNTIME_DIR="${anboxloc}";
137 wantedBy = [ "multi-user.target" ];
139 initsh = pkgs.writeText "nixos-init" (''
141 setprop nixos.version ${config.system.nixos.version}
143 # we don't have radio
144 setprop ro.radio.noril yes
148 setprop debug.sf.nobootanimation 1
150 initshloc = "${anboxloc}/rootfs-overlay/system/etc/init.goldfish.sh";
153 mkdir -p $(dirname ${initshloc})
154 [ -f ${initshloc} ] && rm ${initshloc}
155 cp ${initsh} ${initshloc}
156 chown 100000:100000 ${initshloc}
157 chmod +x ${initshloc}
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 \