diff --git a/config.yaml b/config.yaml index 6880e924..b769fe08 100644 --- a/config.yaml +++ b/config.yaml @@ -16,9 +16,14 @@ zones: flags: 0 tag: issuewild value: ; + - kind: txt + value: v=spf1 include:_spf.google.com -all - kind: mx priority: 1 value: aspmx.l.google.com + - kind: txt + name: google._domainkey + value: v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkxag/EmXQ89XQmLrBDPpPtZ7EtEJT0hgvWf/+AFiOfBOm902tq9NbTTvRJ2dLeBLPaV+hNvq2Alc7UfkKUDlLTWQjeuiC6aOnRKQQg3LZ2W25U3AlIj0jd2IPiUhg9JGV4c66XiqQ5ylTBniShfUUyeAXxbPhYFBCkBg62LZcO/tFpFsdKWtZzLjgac5vTJID+M4F8duHpkA/ZCNNUEmtt7RNQB/LLI1Gr5yR4GdQl9z7NmwtOTo9pghbZuvljr8phYjdDrwZeFTMKQnvR1l2Eh/dZ8I0C4nP5Bk4QEfmLq666P1HzOxwT6iCU6Tc+P/pkWbrx0HJh39E1aKGyLJMQIDAQAB - kind: mx priority: 5 value: alt1.aspmx.l.google.com @@ -34,3 +39,10 @@ zones: - kind: mx priority: 15 value: 6uyykkzhqi4zgogxiicbuamoqrxajwo5werga4byh77b2iyx3wma.mx-verification.google.com + dork: + name: dork.dev + records: + - kind: txt + name: google._domainkey + value: v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAziwoHJbM1rmeUiIXOgg0cujTL5BFW9PQOksUhKza1XpDP2rpzTlQr21NFYMJMc08xiE3AbvScMTX0jX3gc7+XoIYLD1VigRRvkyTubVfRmatqj+Pk41Fle1jWXHv5vNIYjjcsUTrpnrXYKoYrz34TtsmYHnu0G9MgmmcQGmbRU+WY+1R/ukhavlgXasfEW6r4tjLgVxQnser1Zjr80AUcu23od/+o+m6C9rDGMMnv6NIc2DOT7Ei6o60458f2Iwcpg38te22dy46A8AeGynbpB9+jF33Se0m22eKk5qZN5mfju/wxWMsl7ifCY/eqLZXRxJaEd5bMI8px5KvZp1TWwIDAQAB + diff --git a/darwin/common/system.nix b/darwin/common/system.nix index 9269ea7a..4d234fa7 100644 --- a/darwin/common/system.nix +++ b/darwin/common/system.nix @@ -4,6 +4,7 @@ _: { defaults = { SoftwareUpdate.AutomaticallyInstallMacOSUpdates = true; NSGlobalDomain = { + ApplePressAndHoldEnabled = true; AppleInterfaceStyleSwitchesAutomatically = true; AppleShowAllFiles = true; AppleShowAllExtensions = true; diff --git a/iac/device.go b/iac/device.go index ddf83fa1..47f30402 100644 --- a/iac/device.go +++ b/iac/device.go @@ -71,7 +71,7 @@ func (d *Device) handle(ctx *pulumi.Context, zone *Zone, CAKey *tls.PrivateKey, if err != nil { return err } - if d.Hostname != "koishi" { + if d.Hostname != "koishi" && d.Hostname != "tewi" { return err } err = d.handleTLS(CAKey, CACert) diff --git a/iac/files.go b/iac/files.go index a42f1600..cda98bd9 100644 --- a/iac/files.go +++ b/iac/files.go @@ -9,14 +9,20 @@ func CreatePulumiFile(ctx *pulumi.Context, name string, fqdn string, value pulum environment := goMapToPulumiMap(map[string]string{ "PULUMI_SKIP_UPDATE_CHECK": "true", }) - return remote.NewCommand(ctx, name, &remote.CommandArgs{ + port := 22 + user := "deploy" + if fqdn == "tewi.inskip.me" { + port = 62954 + user = "root" + } + return remote.NewCommand(ctx, name, &remote.CommandArgs{ Connection: &remote.ConnectionArgs{ Host: pulumi.String(fqdn), - Port: pulumi.Float64Ptr(22), - User: pulumi.String("deploy"), + Port: pulumi.Float64Ptr(float64(port)), + User: pulumi.String(user), AgentSocketPath: pulumi.String("/Users/kat/.gnupg/S.gpg-agent.ssh"), }, - Create: pulumi.Sprintf("sudo mkdir -p /var/lib/secrets && sudo chown deploy:users -R /var/lib/secrets && cd /var/lib/secrets && echo \"%s\" > \"%s\"", value, name), + Create: pulumi.Sprintf("sudo mkdir -p /var/lib/secrets && cd /var/lib/secrets && echo \"%s\" | sudo tee \"%s\"", value, name), Delete: pulumi.Sprintf("cd /var/lib/secrets && rm %s", name), Environment: environment, }, pulumi.DependsOn(resources)) diff --git a/kat/user/nixos.nix b/kat/user/nixos.nix index 128653a4..173e728c 100644 --- a/kat/user/nixos.nix +++ b/kat/user/nixos.nix @@ -2,7 +2,6 @@ users.users.kat = { uid = 1000; isNormalUser = true; - hashedPassword = "$6$G26zDwcywO6$YzHK1YI6X0d7x/mV6maCx6B7V3M1JdE3VqxxjNc7muxUPkZo0YYwniAB2"; openssh.authorizedKeys = { inherit (tree.kat.user.data) keys; }; diff --git a/nixos/arc.nix b/nixos/arc.nix new file mode 100644 index 00000000..14e99a9d --- /dev/null +++ b/nixos/arc.nix @@ -0,0 +1,17 @@ +{ ... }: { + imports = [ + ({ config, pkgs, ... }: + + { + users.users.arc = { + uid = 1001; + isNormalUser = true; + extraGroups = [ "wheel" ]; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ8Z6briIboxIdedPGObEWB6QEQkvxKvnMW/UVU9t/ac mew-pgp" + ]; + shell = pkgs.zsh; + }; + }) + ]; +} diff --git a/nixos/gensokyo/home-assistant.nix b/nixos/gensokyo/home-assistant.nix new file mode 100644 index 00000000..9277c283 --- /dev/null +++ b/nixos/gensokyo/home-assistant.nix @@ -0,0 +1,429 @@ +{ config, lib, tf, ... }: let + inherit (lib.attrsets) attrNames filterAttrs mapAttrs' nameValuePair; + inherit (lib.strings) hasPrefix; +in { + # MDNS + services.avahi.enable = true; + + networking.firewall = { + allowedTCPPorts = [ + 8123 # Home Assistant + 21036 # HomeKit + ]; + allowedUDPPorts = [ + 5353 # MDNS + ]; + allowedUDPPortRanges = [ + { from = 32768; to = 60999; } # Chromecast + ]; + }; + + networks.gensokyo = { + tcp = [ + # Home Assistant + 8123 + # Tewi Homekit + 21063 + ]; + udp = [ + # Chromecast + [ 32768 60999 ] + # MDNS + 5353 + ]; + }; + + secrets.variables.ha-integration = { + path = "gensokyo/home-assistant"; + field = "notes"; + }; + + secrets.files.ha-integration = { + text = tf.variables.ha-integration.ref; + owner = "hass"; + group = "hass"; + }; + + secrets.variables.latitude = { + path = "gensokyo/home-assistant"; + field = "latitude"; + }; + + secrets.variables.longitude = { + path = "gensokyo/home-assistant"; + field = "longitude"; + }; + + secrets.variables.elevation = { + path = "gensokyo/home-assistant"; + field = "elevation"; + }; + + secrets.variables.iphone-se-irk = { + path = "gensokyo/home-assistant"; + field = "iphone-se-irk"; + }; + secrets.variables.companion-pixel6 = { + path = "gensokyo/home-assistant"; + field = "companion-pixel6"; + }; + secrets.variables.tile-bee = { + path = "gensokyo/home-assistant"; + field = "tile-bee"; + }; + secrets.variables.tile-kat-wallet = { + path = "gensokyo/home-assistant"; + field = "tile-kat-wallet"; + }; + secrets.variables.tile-kat-keys = { + path = "gensokyo/home-assistant"; + field = "tile-kat-keys"; + }; + secrets.variables.mpd-shanghai-password = { + path = "gensokyo/abby"; + field = "mpd"; + }; + + secrets.files.home-assistant-secrets = { + text = let + espresenceDevices = { + iphone-se-irk = tf.variables.iphone-se-irk.ref; + companion-pixel6 = tf.variables.companion-pixel6.ref; + tile-kat-wallet = tf.variables.tile-kat-wallet.ref; + tile-kat-keys = tf.variables.tile-kat-keys.ref; + tile-bee = tf.variables.tile-bee.ref; + }; + in builtins.toJSON ({ + latitude = tf.variables.latitude.ref; + longitude = tf.variables.longitude.ref; + elevation = tf.variables.elevation.ref; + mpd-shanghai-password = tf.variables.mpd-shanghai-password.ref; + } // espresenceDevices // mapAttrs' (key: device_id: + nameValuePair "${key}-topic" "espresense/devices/${device_id}" + ) espresenceDevices); + owner = "hass"; + group = "hass"; + }; + + systemd.services.home-assistant = { + preStart = lib.mkBefore '' + cp --no-preserve=mode ${config.secrets.files.home-assistant-secrets.path} ${config.services.home-assistant.configDir}/secrets.yaml + cp --no-preserve=mode ${config.secrets.files.ha-integration.path} ${config.services.home-assistant.configDir}/integration.yaml + # UI-editable config files + touch ${config.services.home-assistant.configDir}/{automations,scenes,scripts,manual}.yaml + ''; + }; + + services.home-assistant = { + enable = true; + config = { + homeassistant = { + name = "Gensokyo"; + unit_system = "metric"; + latitude = "!secret latitude"; + longitude = "!secret longitude"; + elevation = "!secret elevation"; + currency = "CAD"; + time_zone = "America/Vancouver"; + external_url = "https://home.gensokyo.zone"; + packages = { + manual = "!include manual.yaml"; + }; + }; + frontend = { + themes = "!include_dir_merge_named themes"; + }; + powercalc = { + }; + utility_meter = { + }; + withings = { + use_webhook = true; + }; + logger = { + default = "info"; + }; + http = { + cors_allowed_origins = [ + "https://google.com" + "https://www.home-assistant.io" + ]; + use_x_forwarded_for = "true"; + trusted_proxies = [ + "127.0.0.0/24" + "200::/7" + "100.64.0.0/10" + "fd7a:115c:a1e0:ab12::/64" + ]; + }; + recorder = { + db_url = "postgresql://@/hass"; + auto_purge = true; + purge_keep_days = 14; + commit_interval = 1; + exclude = { + domains = [ + "automation" + "updater" + ]; + entity_globs = [ + "sensor.weather_*" + "sensor.date_*" + ]; + entities = [ + "sun.sun" + "sensor.last_boot" + "sensor.date" + "sensor.time" + ]; + event_types = [ + "call_service" + ]; + }; + }; + google_assistant = { + project_id = "gensokyo-5cfaf"; + service_account = "!include integration.yaml"; + report_state = true; + exposed_domains = [ + "scene" + "script" + "climate" + #"sensor" + ]; + entity_config = let + hidden = "XYZ"; + in { + # bedroom entities + "light.bedside_lamp".expose = true; + "light.bedroom_strip".expose = true; + "light.bedroom_overhead".expose = true; + "light.bed_side_overhead".room = hidden; + "light.closet_side_overhead".room = hidden; + "light.pc_side_overhead".room = hidden; + "light.closet_overhead".expose = true; + "light.closet_overhead_left".room = hidden; + "light.closet_overhead_right".room = hidden; + "fan.bedroom_purifier" = { + expose = true; + aliases = [ + "FÖRNUFTIG" + "Bedroom Air Purifier" + ]; + }; + "fan.bedroom_floor".expose = true; + "switch.swb1_relay_3".expose = true; + "switch.swb1_relay_4".expose = true; + + # living room entities + "light.dining_overhead".expose = true; + "light.living_cluster".expose = true; + "light.living_overhead".room = hidden; + "light.tv_overhead".room = hidden; + "light.couch_overhead_left".room = hidden; + "light.couch_overhead_right".room = hidden; + "light.tv_bias" = { + room = hidden; + aliases = [ + "Bias Lighting" + "TV Backlight" + ]; + }; + "light.living_bookshelf".room = hidden; + # midea + "climate.living_ac".aliases = [ + "AC" + "Midea" + ]; + "sensor.living_ac_outdoor_temperature".expose = false; + + # kitchen + "light.kitchen_overhead".expose = true; + "light.kitchen_overhead_inner".room = hidden; + "light.kitchen_overhead_middle".room = hidden; + "light.kitchen_overhead_outer".room = hidden; + + # balcony + "light.outdoor_strip".expose = true; + "light.lantern".expose = true; + + # foyer + "light.entry_overhead".expose = true; + "light.entry_overhead_left".room = hidden; + "light.entry_overhead_right".room = hidden; + + # shanghai systemd + "switch.shanghai_graphical".expose = true; + "switch.shanghai_mradio".expose = true; + "switch.shanghai_vm_goliath1650".expose = true; + "switch.shanghai_vm_goliath3080".expose = true; + "switch.shanghai_vm_hourai1650".expose = true; + "switch.shanghai_vm_hourai3080".expose = true; + "cover.shanghai_dpms" = { + expose = true; + aliases = [ + "DPMS" + ]; + }; + }; + }; + homekit = { + name = "Tewi"; + port = 21063; + ip_address = "10.1.1.38"; + filter = let + inherit (config.services.home-assistant.config) google_assistant; + entities = filterAttrs (_: entity: entity.expose or true) google_assistant.entity_config; + in { + include_domains = google_assistant.exposed_domains; + include_entities = attrNames (removeAttrs entities [ + # HomeKit is able to group lights together, no need to use the google hack here + "light.living_cluster" + "light.bedroom_overhead" + "light.closet_overhead" + "light.kitchen_overhead" + "light.entry_overhead" + ]); + }; + entity_config = { + "switch.swb1_relay_3".type = "outlet"; + "switch.swb1_relay_4".type = "outlet"; + }; + }; + tts = [{ + platform = "google_translate"; + service_name = "google_say"; + }]; + # https://nixos.wiki/wiki/Home_Assistant#Combine_declarative_and_UI_defined_automations + "automation manual" = [ ]; + "automation ui" = "!include automations.yaml"; + # https://nixos.wiki/wiki/Home_Assistant#Combine_declarative_and_UI_defined_scenes + "scene manual" = []; + "scene ui" = "!include scenes.yaml"; + "script manual" = []; + "script ui" = "!include scripts.yaml"; + counter = {}; + device_tracker = {}; + energy = {}; + group = {}; + history = {}; + image = {}; + input_boolean = {}; + input_button = {}; + input_datetime = {}; + input_number = {}; + input_select = {}; + input_text = {}; + logbook = {}; + schedule = {}; + map = {}; + media_source = {}; + media_player = [ + { + platform = "mpd"; + name = "Shanghai MPD"; + host = "10.1.1.32"; + password = "!secret mpd-shanghai-password"; + } + ]; + mobile_app = {}; + my = {}; + person = {}; + ssdp = {}; + switch = {}; + stream = {}; + sun = {}; + system_health = {}; + tag = {}; + template = {}; + tile = {}; + timer = {}; + webhook = {}; + wake_on_lan = {}; + zeroconf = {}; + zone = {}; + sensor = let + mkESPresenceBeacon = { device_id, ... }@args: { + platform = "mqtt_room"; + state_topic = if hasPrefix "!secret" device_id + then "${device_id}-topic" + else "espresense/devices/${device_id}"; + } // args; + in [ + (mkESPresenceBeacon { + device_id = "!secret iphone-se-irk"; + name = "iPhone SE"; + timeout = 2; + away_timeout = 120; + }) + (mkESPresenceBeacon { + device_id = "!secret companion-pixel6"; + name = "Kat's Pixel 6"; + timeout = 5; + away_timeout = 120; + }) + (mkESPresenceBeacon { + device_id = "name:galaxy-watch-active"; + name = "Galaxy Watch Active"; + }) + (mkESPresenceBeacon { + device_id = "3003c8383b6c"; + name = "MT7922 BT"; + }) + (mkESPresenceBeacon { + device_id = "d8f8833681ba"; + name = "AX210 BT"; + }) + (mkESPresenceBeacon { + device_id = "md:03ff:6"; + name = "Kat's Smartwatch"; + }) + (mkESPresenceBeacon { + device_id = "!secret tile-bee"; + name = "Bee"; + }) + (mkESPresenceBeacon { + device_id = "!secret tile-kat-wallet"; + name = "Kat's Wallet"; + }) + (mkESPresenceBeacon { + device_id = "!secret tile-kat-keys"; + name = "Girlwife"; + }) + ]; + }; + extraPackages = python3Packages: with python3Packages; [ + psycopg2 + aiohomekit + securetar + getmac # for upnp integration + (aiogithubapi.overrideAttrs (_: { doInstallCheck = false; })) + ]; + extraComponents = [ + "automation" + "scene" + "script" + "zha" + "esphome" + "apple_tv" + "spotify" + "default_config" + "brother" + "ipp" + "cast" + "plex" + "met" + "google" + "google_assistant" + "google_cloud" + "google_translate" + "homekit" + "mpd" + "mqtt" + "tile" + "wake_on_lan" + "withings" + "zeroconf" + ]; + }; +} diff --git a/systems/chen.nix b/systems/chen.nix index 191c9946..f1d21856 100644 --- a/systems/chen.nix +++ b/systems/chen.nix @@ -8,6 +8,12 @@ _: let networking.firewall.enable = mkForce false; + boot.kernel.sysctl = mkForce {}; + + systemd.services = { + systemd-sysctl.enable = false; + }; + fileSystems = { "/" = { device = "/dev/sdc"; diff --git a/systems/sumireko.nix b/systems/sumireko.nix index c440c4ea..77cc4b1f 100644 --- a/systems/sumireko.nix +++ b/systems/sumireko.nix @@ -25,6 +25,7 @@ _: let brews = [ "gnupg" "pinentry-mac" + "awscurl" ]; casks = [ "utm" diff --git a/systems/tewi.nix b/systems/tewi.nix new file mode 100644 index 00000000..2247c4af --- /dev/null +++ b/systems/tewi.nix @@ -0,0 +1,84 @@ +_: let + hostConfig = {tree, lib, ...}: let + inherit (lib.modules) mkForce; + in { + imports = with tree; [ + nixos.arc +/* ./kanidm.nix + ./vouch.nix + ./home-assistant.nix + ./zigbee2mqtt.nix + ./mosquitto.nix + ./postgres.nix + ./nginx.nix + ../../gui/nfs.nix */ + ]; + + + networking = { + useDHCP = false; + interfaces = { + eno1 = { + useDHCP = true; + }; + }; + }; + + boot = { + loader = { + systemd-boot = { + enable = true; + }; + efi = { + canTouchEfiVariables = true; + }; + }; + initrd = { + availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; + }; + kernelModules = [ "kvm-intel" ]; + }; + +/* services.openiscsi = { + enable = true; + name = ""; + discoverPortal = "shanghai.tail.cutie.moe"; + }; + + environment.etc."iscsi/initiatorname.iscsi" = mkForce { + source = config.secrets.files.openscsi-config.path; + }; + + secrets.variables.openscsi-password = { + path = "gensokyo/tewi-scsi"; + field = "password"; + }; + + secrets.files.openscsi-config = { + text = "InitiatorName=${tf.variables.openscsi-password.ref}"; + }; */ + + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/6c5d82b1-5d11-4c72-96c6-5f90e6ce57f5"; + fsType = "ext4"; + }; + "/boot" = { + device = "/dev/disk/by-uuid/85DC-72FA"; + fsType = "vfat"; + }; + }; + + swapDevices = lib.singleton ({ + device = "/dev/disk/by-uuid/137605d3-5e3f-47c8-8070-6783ce651932"; + }); + + system.stateVersion = "21.05"; +}; +in { + arch = "x86_64"; + type = "NixOS"; + modules = [ + hostConfig + ]; +}