~tcarrio/clusta

0f4fe76ed810f186bf8a6508ff5924abd0711c2b — Tom Carrio 9 months ago 62abf99 master
feat: system config with tailscale module ssh and more
A iac/nuc/.gitignore => iac/nuc/.gitignore +2 -0
@@ 0,0 1,2 @@
/secret.nix
/result
\ No newline at end of file

M iac/nuc/Makefile => iac/nuc/Makefile +18 -1
@@ 1,7 1,24 @@
.PHONY: boot-iso clean

all: has_target_device clean boot-iso push

boot-iso:
	nix-build '<nixpkgs/nixos>' -A config.system.build.isoImage -I nixos-config=./iso.nix

clean:
	rm -rf ./result
\ No newline at end of file
	rm -rf ./result

push: has_target_device
	@echo 'Requesting sudo access...'
	@sudo echo
	@find ./result/iso -type f -exec sudo dd if="{}" of=$(target_device) status=progress \;

has_target_device:
ifdef target_device
	@echo 'testing target_device exists...'
	@test -e $(target_device)
	@echo 'found path for target device'
else
	@echo 'target_device IS NOT defined, cannot push to device'
	@exit 1
endif
\ No newline at end of file

M iac/nuc/README.md => iac/nuc/README.md +10 -0
@@ 2,6 2,16 @@

These configurations are defined for my NUC devices.

## configuration

You **must** configure a `secret.nix` file. You can copy the example:

```bash
cp ./secret.example.nix ./secret.nix
```

This provides certain values at build time, such as the Tailscale auth token.

## installer iso

You can create an installation ISO image which can be useful for getting a machine up and running.

A iac/nuc/configuration.nix => iac/nuc/configuration.nix +157 -0
@@ 0,0 1,157 @@
# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).

{ config, pkgs, ... }:

{
  imports =
    [
      # Include the results of the hardware scan.
      ./hardware-configuration.nix

      # Pull in our desired modules
      ./modules/tailscale.nix

      # Must inject for secret config values
      ./secret.nix 
    ];

  boot = {
    # Use the systemd-boot EFI boot loader.
    loader.systemd-boot.enable = true;
    loader.efi.canTouchEfiVariables = true;

    # Set a custom kernel package
    # kernelPackages = pkgs.linux_latest;
  };


  # Set your time zone.
  time.timeZone = "America/Detroit";

  networking = {
    hostName = "nuc"; # Define your hostname.
    wireless.enable = false;  # Enables wireless support via wpa_supplicant.

    # The global useDHCP flag is deprecated, therefore explicitly set to false here.
    # Per-interface useDHCP will be mandatory in the future, so this generated config
    # replicates the default behaviour.
    useDHCP = false;
    
    # IP addresses are preconfigured for NUCs by MAC address in the DHCP server
    interfaces.enp2s0.useDHCP = true;

    enableIPv6 = true;

    # Configure network proxy if necessary
    # proxy.default = "http://user:password@proxy:port/";
    # proxy.noProxy = "127.0.0.1,localhost,internal.domain";
  };


  # Select internationalisation properties.
  # i18n.defaultLocale = "en_US.UTF-8";
  # console = {
  #   font = "Lat2-Terminus16";
  #   keyMap = "us";
  # };

  # Enable the X11 windowing system.
  # services.xserver.enable = true;

  # Configure keymap in X11
  services.xserver.layout = "us";
  # services.xserver.xkbOptions = "eurosign:e";

  # Enable CUPS to print documents.
  # services.printing.enable = true;

  # Enable sound.
  # sound.enable = true;
  # hardware.pulseaudio.enable = true;

  # Enable touchpad support (enabled default in most desktopManager).
  # services.xserver.libinput.enable = true;

  # Configure virtualization & containerization tooling
  virtualisation = {
    podman = {
      enable = true;

      # Create a `docker` alias for podman, to use it as a drop-in replacement
      dockerCompat = true;

      # Required for containers under podman-compose to be able to talk to each other.
      # defaultNetwork.settings = {
      #   dns_enabled = true;
      # };
    };

    ## Manage docker containers as systemd services
    # oci-containers = {
    #   backend = "podman";
    #   containers = {
    #     container-name = {
    #       image = "container-image";
    #       autoStart = true;
    #       ports = [ "127.0.0.1:1234:1234" ];
    #     };
    #   };
    # };
  };

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.tom = {
    description = "Tom Carrio";
    extraGroups = [
      "networkmanager" # User can configure networking
      "podman"         # User can work with podman containers
      "wheel"          # User can sudo
    ];
    # mkpasswd -m sha-512
    hashedPassword = "$6$gVQMdBGAzVKbMfE$FC84w0xc.O2mBR4OLNJE2Vb/.QcDd90vQB48tb/h0dYVHlWoBvBjZ8q26WwvOBvq8G6qz8CzrUgrm8lYU2jpd/";
    isNormalUser = true;
    openssh.authorizedKeys.keys = [
      "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCwWh/r0uIecKBu8B7ZaoKPZbfimAarWI2WYMsIIeOumJUyXNk8nEUzLRUvpak60QNWy1m7sTyEUhQZDoKT0q0oZzG+yNKBWgA4Q+A2ISBtBW4uil/OTK3ZrIQKmTzUYFYChQfZkjj4j/bdpzdxlyaNC7bnxS4T3Lia0LBjMDlPaXPOKbliV2rTlm81wF6SN3a9SPNjLrpDv8SJFU4qEY5ZTv8LXHABWmRN4TZTRMO6Or6OrYl9o/uBtGlQGpwsbl2CCaAlrpub/oaYCm15uCKmMwbmqo+zsBmAcpwbg43zBDy4PL9AZUhyyaLlF5/5Ypb4JkRdplObLmwzp6P7uUGn5mEIsLJrU25M0Bc6iIOxu1WZzEfrBRJblTx8501//FVJwVHdl+oYWG/BdF06ELTvUhWnjuhUu2wCaSfeeZxBegBJKz7lfjtCCvSPM64H6J/jqVPbJJuOUu4n0nv7Wizyn2JudlfyUqZ/D1B5z2KExScLrRH5IFebLTLRA6/HTpjltjb5bc+T+CB/rvXWVrfMRogVRixpcgzKwlFjgj5WcP+jBxDiU6te+5KuJrHZc+3m5HXkC4lFDYX42fSSnae40a11YAYu5OKBcOszVok1TFZD5Lhw5k0XrAUN28mRUzbUKbxfxHI+X5OU7ekSfcqNNy6yY5wvy9ZpLI1p6NloGw== tom@carrio.dev"
    ];
    packages = [];
    shell = pkgs.fish;
  };

  programs.fish.enable = true;

  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
    vim
  ];

  # Some programs need SUID wrappers, can be configured further or are
  # started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };

  # List services that you want to enable:

  # Enable the OpenSSH daemon.
  services.openssh.enable = true;

  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  # networking.firewall.enable = false;

  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "21.11"; # Did you read the comment?

}

A iac/nuc/hardware-configuration.nix => iac/nuc/hardware-configuration.nix +28 -0
@@ 0,0 1,28 @@
# Do not modify this file!  It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations.  Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:

{
  imports =
    [ (modulesPath + "/installer/scan/not-detected.nix")
    ];

  boot.initrd.availableKernelModules = [ "xhci_pci" "usb_storage" "sd_mod" "sdhci_acpi" ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ "kvm-intel" ];
  boot.extraModulePackages = [ ];

  fileSystems."/" =
    { device = "/dev/disk/by-uuid/99da18a6-8471-4103-aa81-d244fc8c33cd";
      fsType = "ext4";
    };

  fileSystems."/boot" =
    { device = "/dev/disk/by-uuid/7E88-5C5D";
      fsType = "vfat";
    };

  swapDevices = [ ];

}

A iac/nuc/modules/tailscale.nix => iac/nuc/modules/tailscale.nix +37 -0
@@ 0,0 1,37 @@
{ config, pkgs, ... }:
{
  # Install the Tailscale client to the PATH
  environment.systemPackages = [ pkgs.tailscale ];

  # Enable the Tailscale service to connect to the mesh
  services.tailscale.enable = true;

  # Setup autoconnect systemd unit
  systemd.services.tailscale-autoconnect = {
    description = "Automatic connection to Tailscale";

    # make sure tailscale is running before trying to connect to tailscale
    after = [ "network-pre.target" "tailscale.service" ];
    wants = [ "network-pre.target" "tailscale.service" ];
    wantedBy = [ "multi-user.target" ];

    # set this service as a oneshot job
    serviceConfig.Type = "oneshot";

    # have the job run this shell script
    script = with pkgs; ''
      # wait for tailscaled to settle
      sleep 2

      # check if we are already authenticated to tailscale
      status="$(${tailscale}/bin/tailscale status -json | ${jq}/bin/jq -r .BackendState)"
      if [ $status = "Running" ]; then # if so, then do nothing
        exit 0
      fi

      # otherwise authenticate with tailscale
      ${tailscale}/bin/tailscale up -authkey ${config.tailscale_token}
    '';
  };

}
\ No newline at end of file

A iac/nuc/secret.example.nix => iac/nuc/secret.example.nix +4 -0
@@ 0,0 1,4 @@
{ config, ... }:
{
  config.tailscale_token = "a-one-off-tailscale-token";
}
\ No newline at end of file