liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

bordervm-configuration.nix (5966B)


      1 nixpkgs:
      2 {
      3   config,
      4   pkgs,
      5   lib,
      6   ...
      7 }:
      8 let
      9   cfg = config.bordervm;
     10   inherit (lib)
     11     mkOption
     12     mkEnableOption
     13     mdDoc
     14     types
     15     optional
     16     optionals
     17     ;
     18 in
     19 {
     20   options.bordervm = {
     21     keys = mkOption {
     22       type = types.listOf types.str;
     23       default = [ ];
     24     };
     25     l2tp = {
     26       host = mkOption {
     27         description = mdDoc ''
     28           Hostname or IP address of an L2TP LNS that this VM
     29           will connect to when it receives a PPPoE connection request
     30         '';
     31         type = types.str;
     32         example = "l2tp.example.org";
     33       };
     34       port = mkOption {
     35         description = mdDoc ''
     36           Port number, if non-standard, of the LNS.
     37         '';
     38         type = types.int;
     39         default = 1701;
     40       };
     41     };
     42     ethernet = {
     43       pci = {
     44         enable = mkEnableOption "passthru PCI ethernet";
     45         id = mkOption {
     46           description = ''
     47             Host PCI ID (as shown by `lspci`) of the ethernet adaptor
     48             to be used by the VM. This uses VFIO and requires setup
     49             on the emulation host before it will work!
     50           '';
     51           type = types.str;
     52           example = "04:00.0";
     53         };
     54       };
     55       usb = {
     56         enable = mkEnableOption "passthru USB ethernet";
     57         vendor = mkOption {
     58           type = types.str;
     59           example = "0x0bda";
     60         };
     61         product = mkOption {
     62           type = types.str;
     63           example = "0x8153";
     64         };
     65       };
     66     };
     67   };
     68   imports = [
     69     "${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
     70   ];
     71   config = {
     72     boot.kernelParams = [ "loglevel=9" ];
     73     systemd.services.pppoe =
     74       let
     75         conf = pkgs.writeText "kpppoed.toml" ''
     76           interface_name = "eth1"
     77           services = [ "myservice" ]
     78           lns_ipaddr = "${cfg.l2tp.host}:${builtins.toString cfg.l2tp.port}"
     79           ac_name = "kpppoed-1.0"
     80         '';
     81       in
     82       {
     83         wantedBy = [ "multi-user.target" ];
     84         after = [ "network-online.target" ];
     85         serviceConfig = {
     86           ExecStart = "${pkgs.go-l2tp}/bin/kpppoed -config ${conf}";
     87         };
     88       };
     89     systemd.services.tufted = {
     90       wantedBy = [ "multi-user.target" ];
     91       serviceConfig = {
     92         ExecStart = "${pkgs.tufted}/bin/tufted /home/liminix/liminix";
     93       };
     94     };
     95     services.openssh.enable = true;
     96     services.dnsmasq = {
     97       enable = true;
     98       resolveLocalQueries = false;
     99       settings = {
    100         # domain-needed = true;
    101         dhcp-range = [ "10.0.0.12,10.0.0.240" ];
    102         interface = "eth1";
    103       };
    104     };
    105 
    106     services.nginx = {
    107       enable = true;
    108       user = "liminix";
    109       virtualHosts.${config.networking.hostName} = {
    110         root = "/home/liminix";
    111         default = true;
    112       };
    113     };
    114     systemd.services.nginx.serviceConfig.ProtectHome = "read-only";
    115 
    116     systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
    117 
    118     virtualisation = {
    119       forwardPorts = [
    120         # {
    121         #   # guest tang service exposed on host for easy querying
    122         #   from = "host";
    123         #   host.port = 7654;
    124         #   guest.port = 7654;
    125         # }
    126         {
    127           host.port = 2222;
    128           guest.address = "10.0.2.15";
    129           guest.port = 22;
    130         }
    131         {
    132           # expose victorialogs on host so (clients attached to) guest
    133           # can log
    134           from = "guest"; # packets are forwarded from guest
    135           guest.address = "10.0.2.10";
    136           guest.port = 443;
    137           host.address = "127.0.0.1";
    138           host.port = 443;
    139         }
    140         {
    141           from = "guest"; # packets are forwarded from guest
    142           guest.address = "10.0.2.10";
    143           guest.port = 19613;
    144           host.address = "127.0.0.1";
    145           host.port = 19613;
    146         }
    147       ];
    148       qemu = {
    149         networkingOptions = [ ];
    150         options =
    151           [ ]
    152           ++ optional cfg.ethernet.pci.enable "-device vfio-pci,host=${cfg.ethernet.pci.id}"
    153           ++ optionals cfg.ethernet.usb.enable [
    154             "-device qemu-xhci"
    155             # "-device usb-ehci,id=ehci"
    156             # "-device usb-host,bus=ehci.0,vendorid=${cfg.ethernet.usb.vendor},productid=${cfg.ethernet.usb.product}"
    157             "-device usb-host,vendorid=${cfg.ethernet.usb.vendor},productid=${cfg.ethernet.usb.product}"
    158           ]
    159           ++ [
    160             "-nographic"
    161             "-serial mon:stdio"
    162           ];
    163       };
    164       sharedDirectories = {
    165         liminix = {
    166           source = builtins.toString ./.;
    167           target = "/home/liminix/liminix";
    168         };
    169       };
    170     };
    171 
    172     services.tang = {
    173       enable = true;
    174       ipAddressAllow = [
    175         "10.0.0.0/24"
    176         "0.0.0.0/0"
    177       ];
    178     };
    179 
    180     environment.systemPackages =
    181       let
    182         wireshark-nogui = pkgs.wireshark.override { withQt = false; };
    183       in
    184       with pkgs;
    185       [
    186         tcpdump
    187         wireshark-nogui
    188         socat
    189         tufted
    190         iptables
    191         usbutils
    192         busybox
    193         clevis
    194       ];
    195     security.sudo.wheelNeedsPassword = false;
    196     networking = {
    197       hostName = "border";
    198       firewall = {
    199         enable = false;
    200       };
    201       interfaces.eth1 = {
    202         useDHCP = false;
    203         ipv4.addresses = [
    204           {
    205             address = "10.0.0.1";
    206             prefixLength = 24;
    207           }
    208         ];
    209       };
    210       nat = {
    211         enable = true;
    212         internalInterfaces = [ "eth1" ];
    213         externalInterface = "eth0";
    214         extraCommands = ''
    215           portfwd() {
    216             iptables -t nat -A PREROUTING -p tcp --dport $2 -j DNAT --to-destination $1:$2
    217             iptables -t nat -A POSTROUTING -p tcp -d $1 --dport $2 -j SNAT --to-source 10.0.0.1
    218           }
    219           portfwd 10.0.2.10 443
    220           portfwd 10.0.2.10 19613
    221         '';
    222       };
    223     };
    224     users.users.liminix = {
    225       isNormalUser = true;
    226       uid = 1000;
    227       extraGroups = [ "wheel" ];
    228       openssh.authorizedKeys.keys = cfg.keys;
    229     };
    230     services.getty.autologinUser = "liminix";
    231   };
    232 }