#cloud-config
# Minimal user-data: download bootstrap.sh from your file server and run it at first boot.
#
# 1. Host bootstrap.sh at a URL reachable from the device on first boot (e.g. your
#    provisioning portal or file server). Example: http://10.20.50.1:5000/files/bootstrap.sh
# 2. Copy this file to the boot partition as "user-data" (with meta-data and optional network-config).
# 3. Edit BOOTSTRAP_URL below to match your server (or set it once in the runcmd section).
#
# DNS: This config uses systemd-resolved; /etc/resolv.conf is a stub and DNS comes from DHCP
# (LXC option 6). Ensure bootstrap.sh does not overwrite /etc/resolv.conf. See docs/DEVICE-DNS-DHCP-RESOLVCONF.md.

package_update: true
package_upgrade: false

# Keep /etc/hosts in sync with hostname (from meta-data or set below)
manage_etc_hosts: true

# DNS is managed by systemd-resolved; we do not overwrite /etc/resolv.conf
manage_resolv_conf: false

packages:
  - curl

# Ensure SSH is enabled and password auth allowed so you can log in after first boot
write_files:
  - path: /etc/ssh/sshd_config.d/99-cloud-init.conf
    content: |
      PasswordAuthentication yes
      PermitRootLogin no

  # Push current DHCP DNS into systemd-resolved (for dhcpcd/dhclient when NM doesn't feed resolved).
  # With no args: discover DNS from lease or resolvectl and push to resolved for default IF.
  # NetworkManager feeds resolved automatically; this covers first boot and non-NM setups.
  - path: /usr/local/bin/update-resolv-from-dhcp.sh
    content: |
      #!/bin/sh
      # Push DHCP DNS to systemd-resolved so resolv.conf (stub) uses it.
      IF="${IFACE:-$(ip -o -4 route show to default 2>/dev/null | awk '{print $5}' | head -1)}"
      [ -z "$IF" ] && exit 0
      DNS=""
      if [ -s /run/systemd/resolve/resolv.conf ]; then
        DNS=$(grep -E '^nameserver\s+' /run/systemd/resolve/resolv.conf | awk '{print $2}' | tr '\n' ' ')
      fi
      if [ -z "$DNS" ]; then
        DNS=$(resolvectl dns "$IF" 2>/dev/null | tr ' ' '\n' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | tr '\n' ' ')
      fi
      if [ -z "$DNS" ]; then
        LEASE=$(ls /var/lib/dhcp/dhclient.*.leases 2>/dev/null | head -1)
        [ -n "$LEASE" ] && DNS=$(grep -oP 'option domain-name-servers \K[^;]+' "$LEASE" 2>/dev/null | tr ',' '\n' | tr -d ' ' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' | tr '\n' ' ')
      fi
      [ -n "$DNS" ] && resolvectl dns "$IF" $DNS
    permissions: '0755'

  # dhclient: feed systemd-resolved on every lease acquire/renew (DHCP provides new_domain_name_servers)
  - path: /etc/dhcp/dhclient-exit-hooks.d/zzz-update-resolv-conf
    content: |
      #!/bin/sh
      # Run by dhclient on exit; push DHCP DNS into systemd-resolved.
      [ -z "$new_domain_name_servers" ] && exit 0
      [ -z "$interface" ] && exit 0
      resolvectl dns "$interface" $new_domain_name_servers
    permissions: '0755'

  # NetworkManager: resolved is fed by NM by default; this only runs our script as fallback (e.g. if resolved started late).
  - path: /etc/NetworkManager/dispatcher.d/99-update-resolv-from-dhcp
    content: |
      #!/bin/sh
      [ "$2" = "up" ] || [ "$2" = "dhcp4-change" ] || exit 0
      export IFACE="$1"
      /usr/local/bin/update-resolv-from-dhcp.sh
    permissions: '0755'

  # Tell NetworkManager to send DHCP DNS to systemd-resolved (so every DHCP update is applied).
  - path: /etc/NetworkManager/conf.d/99-use-resolved.conf
    content: |
      [main]
      dns=systemd-resolved
      rc-manager=unmanaged

  # Fallback: push DHCP DNS to resolved once when network is up (e.g. dhcpcd-only or first boot).
  - path: /etc/systemd/system/update-resolv-from-dhcp.service
    content: |
      [Unit]
      Description=Push DHCP DNS to systemd-resolved
      After=network-online.target systemd-resolved.service
      WantedBy=network-online.target

      [Service]
      Type=oneshot
      ExecStart=/usr/local/bin/update-resolv-from-dhcp.sh
      RemainAfterExit=yes

runcmd:
  # Use systemd-resolved for DNS; /etc/resolv.conf -> stub so all lookups go through resolved (DHCP DNS applied by NM/hooks).
  - systemctl enable systemd-resolved.service
  - systemctl start systemd-resolved.service
  - rm -f /etc/resolv.conf && ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
  # Push current DHCP DNS into resolved once at first boot (in case NM hasn't applied yet).
  - /usr/local/bin/update-resolv-from-dhcp.sh
  - systemctl enable update-resolv-from-dhcp.service
  - systemctl enable ssh
  - systemctl start ssh
  # Download and run bootstrap script (edit URL to match your file server)
  - |
    BOOTSTRAP_URL="http://file.server:5000/files/bootstrap.sh"
    LOG="/var/log/cloud-init-bootstrap.log"
    if ! curl -fsSL "$BOOTSTRAP_URL" -o /tmp/bootstrap.sh 2>>"$LOG" || [ ! -s /tmp/bootstrap.sh ]; then
      echo "$(date -Iseconds) ERROR: Failed to download bootstrap.sh from $BOOTSTRAP_URL (file missing or empty)" >> "$LOG"
      exit 0
    fi
    chmod +x /tmp/bootstrap.sh
    /tmp/bootstrap.sh
  - cloud-init single --name cc_final_message
