From 369ab99cd15f1b6b87f71a576b5ac332aacd9f49 Mon Sep 17 00:00:00 2001 From: Nikholas Pcenicni <82239765+nikpcenicni@users.noreply.github.com> Date: Fri, 27 Mar 2026 04:01:40 -0400 Subject: [PATCH] Update Cilium application configuration to enable ingress controller and remove deprecated argocd-server service patch; delete Proxmox VM template files. --- .DS_Store | Bin 6148 -> 6148 bytes clusters/noble/apps/cilium/application.yaml | 6 + .../bootstrap/argocd/argocd-ingress.yaml | 21 ++ .../argocd/argocd-server-service-patch.yaml | 21 -- .../noble/bootstrap/argocd/kustomization.yaml | 2 +- coder/proxmox-vm/Readme.md | 161 ---------- coder/proxmox-vm/cloud-init/user-data.tftpl | 53 ---- coder/proxmox-vm/main.tf | 283 ------------------ coder/proxmox-vm/terraform.tfvars | 17 -- komodo/automate/coder/.env.sample | 11 - komodo/automate/coder/compose.yaml | 65 ---- talos/README.md | 14 + 12 files changed, 42 insertions(+), 612 deletions(-) create mode 100644 clusters/noble/bootstrap/argocd/argocd-ingress.yaml delete mode 100644 clusters/noble/bootstrap/argocd/argocd-server-service-patch.yaml delete mode 100644 coder/proxmox-vm/Readme.md delete mode 100644 coder/proxmox-vm/cloud-init/user-data.tftpl delete mode 100644 coder/proxmox-vm/main.tf delete mode 100644 coder/proxmox-vm/terraform.tfvars delete mode 100644 komodo/automate/coder/.env.sample delete mode 100644 komodo/automate/coder/compose.yaml diff --git a/.DS_Store b/.DS_Store index 4fef335851ec8f371e8980c2a814752bdf950e2b..6c5067555d9104f3b9da9e258aa3f4fb657bd840 100644 GIT binary patch delta 32 ocmZoMXfc@J&nU1lU^g?Pz-As6ZpO{iSqqpZ7Bp;T=lIJH0HN^;2mk;8 delta 157 zcmZoMXfc@J&nU7nU^g?P$YvfEZpM06hGd3(h7^WWhN7Hw!{Frn+yVwLFtY$sNV2*4 tE-pzq`AI-gjvMb9rs>T%?uf1;g@B5J3}hP;fZ8{Uu@*9IX6N|J4*(2RCqDoH diff --git a/clusters/noble/apps/cilium/application.yaml b/clusters/noble/apps/cilium/application.yaml index cbf12ca..47a9823 100644 --- a/clusters/noble/apps/cilium/application.yaml +++ b/clusters/noble/apps/cilium/application.yaml @@ -18,6 +18,12 @@ spec: valuesObject: k8sServiceHost: 192.168.50.20 k8sServicePort: 6443 + ingressController: + enabled: true + default: true + loadbalancerMode: shared + hostNetwork: + enabled: true cgroup: autoMount: enabled: false diff --git a/clusters/noble/bootstrap/argocd/argocd-ingress.yaml b/clusters/noble/bootstrap/argocd/argocd-ingress.yaml new file mode 100644 index 0000000..6daf111 --- /dev/null +++ b/clusters/noble/bootstrap/argocd/argocd-ingress.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: argocd-server + namespace: argocd + annotations: + ingress.cilium.io/tls-passthrough: "enabled" +spec: + ingressClassName: cilium + rules: + - host: argo.noble.lab.pcenicni.dev + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: argocd-server + port: + number: 443 + diff --git a/clusters/noble/bootstrap/argocd/argocd-server-service-patch.yaml b/clusters/noble/bootstrap/argocd/argocd-server-service-patch.yaml deleted file mode 100644 index 3a0d5e6..0000000 --- a/clusters/noble/bootstrap/argocd/argocd-server-service-patch.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: argocd-server-lan - namespace: argocd -spec: - type: NodePort - selector: - app.kubernetes.io/name: argocd-server - ports: - - name: http - port: 80 - protocol: TCP - targetPort: 8080 - nodePort: 30080 - - name: https - port: 443 - protocol: TCP - targetPort: 8080 - nodePort: 30443 - diff --git a/clusters/noble/bootstrap/argocd/kustomization.yaml b/clusters/noble/bootstrap/argocd/kustomization.yaml index 423aebd..db3c792 100644 --- a/clusters/noble/bootstrap/argocd/kustomization.yaml +++ b/clusters/noble/bootstrap/argocd/kustomization.yaml @@ -5,5 +5,5 @@ resources: - namespace.yaml - https://raw.githubusercontent.com/argoproj/argo-cd/v2.14.7/manifests/install.yaml - default-appproject.yaml - - argocd-server-service-patch.yaml + - argocd-ingress.yaml diff --git a/coder/proxmox-vm/Readme.md b/coder/proxmox-vm/Readme.md deleted file mode 100644 index ed0fd13..0000000 --- a/coder/proxmox-vm/Readme.md +++ /dev/null @@ -1,161 +0,0 @@ ---- -display_name: Proxmox VM -description: Provision VMs on Proxmox VE as Coder workspaces -icon: ../../../../.icons/proxmox.svg -verified: false -tags: [proxmox, vm, cloud-init, qemu] ---- - -# Proxmox VM Template for Coder - -Provision Linux VMs on Proxmox as [Coder workspaces](https://coder.com/docs/workspaces). The template clones a cloud‑init base image, injects user‑data via Snippets, and runs the Coder agent under the workspace owner's Linux user. - -## Prerequisites - -- Proxmox VE 8/9 -- Proxmox API token with access to nodes and storages -- SSH access from Coder provisioner to Proxmox VE -- Storage with "Snippets" content enabled -- Ubuntu cloud‑init image/template on Proxmox - - Latest images: https://cloud-images.ubuntu.com/ ([source](https://cloud-images.ubuntu.com/)) - -## Prepare a Proxmox Cloud‑Init Template (once) - -Run on the Proxmox node. This uses a RELEASE variable so you always pull a current image. - -```bash -# Choose a release (e.g., jammy or noble) -RELEASE=jammy -IMG_URL="https://cloud-images.ubuntu.com/${RELEASE}/current/${RELEASE}-server-cloudimg-amd64.img" -IMG_PATH="/var/lib/vz/template/iso/${RELEASE}-server-cloudimg-amd64.img" - -# Download cloud image -wget "$IMG_URL" -O "$IMG_PATH" - -# Create base VM (example ID 999), enable QGA, correct boot order -NAME="ubuntu-${RELEASE}-cloudinit" -qm create 999 --name "$NAME" --memory 4096 --cores 2 \ - --net0 virtio,bridge=vmbr0 --agent enabled=1 -qm set 999 --scsihw virtio-scsi-pci -qm importdisk 999 "$IMG_PATH" local-lvm -qm set 999 --scsi0 local-lvm:vm-999-disk-0 -qm set 999 --ide2 local-lvm:cloudinit -qm set 999 --serial0 socket --vga serial0 -qm set 999 --boot 'order=scsi0;ide2;net0' - -# Enable Snippets on storage 'local' (one‑time) -pvesm set local --content snippets,vztmpl,backup,iso - -# Convert to template -qm template 999 -``` - -Verify: - -```bash -qm config 999 | grep -E 'template:|agent:|boot:|ide2:|scsi0:' -``` - -### Enable Snippets via GUI - -- Datacenter → Storage → select `local` → Edit → Content → check "Snippets" → OK -- Ensure `/var/lib/vz/snippets/` exists on the node for snippet files -- Template page → Cloud‑Init → Snippet Storage: `local` → File: your yml → Apply - -## Configure this template - -Edit `terraform.tfvars` with your environment: - -```hcl -# Proxmox API -proxmox_api_url = "https://:8006/api2/json" -proxmox_api_token_id = "!" -proxmox_api_token_secret = "" - -# SSH to the node (for snippet upload) -proxmox_host = "" -proxmox_password = "" -proxmox_ssh_user = "root" - -# Infra defaults -proxmox_node = "pve" -disk_storage = "local-lvm" -snippet_storage = "local" -bridge = "vmbr0" -vlan = 0 -clone_template_vmid = 999 -``` - -### Variables (terraform.tfvars) - -- These values are standard Terraform variables that the template reads at apply time. -- Place secrets (e.g., `proxmox_api_token_secret`, `proxmox_password`) in `terraform.tfvars` or inject with environment variables using `TF_VAR_*` (e.g., `TF_VAR_proxmox_api_token_secret`). -- You can also override with `-var`/`-var-file` if you run Terraform directly. With Coder, the repo's `terraform.tfvars` is bundled when pushing the template. - -Variables expected: - -- `proxmox_api_url`, `proxmox_api_token_id`, `proxmox_api_token_secret` (sensitive) -- `proxmox_host`, `proxmox_password` (sensitive), `proxmox_ssh_user` -- `proxmox_node`, `disk_storage`, `snippet_storage`, `bridge`, `vlan`, `clone_template_vmid` -- Coder parameters: `cpu_cores`, `memory_mb`, `disk_size_gb` - -## Proxmox API Token (GUI/CLI) - -Docs: https://pve.proxmox.com/wiki/User_Management#pveum_tokens - -GUI: - -1. (Optional) Create automation user: Datacenter → Permissions → Users → Add (e.g., `terraform@pve`) -2. Permissions: Datacenter → Permissions → Add → User Permission - - Path: `/` (or narrower covering your nodes/storages) - - Role: `PVEVMAdmin` + `PVEStorageAdmin` (or `PVEAdmin` for simplicity) -3. Token: Datacenter → Permissions → API Tokens → Add → copy Token ID and Secret -4. Test: - -```bash -curl -k -H "Authorization: PVEAPIToken=!=" \ - https:// < PVE_HOST > :8006/api2/json/version -``` - -CLI: - -```bash -pveum user add terraform@pve --comment 'Terraform automation user' -pveum aclmod / -user terraform@pve -role PVEAdmin -pveum user token add terraform@pve terraform --privsep 0 -``` - -## Use - -```bash -# From this directory -coder templates push --yes proxmox-cloudinit --directory . | cat -``` - -Create a workspace from the template in the Coder UI. First boot usually takes 60–120s while cloud‑init runs. - -## How it works - -- Uploads rendered cloud‑init user‑data to `:snippets/.yml` via the provider's `proxmox_virtual_environment_file` -- VM config: `virtio-scsi-pci`, boot order `scsi0, ide2, net0`, QGA enabled -- Linux user equals Coder workspace owner (sanitized). To avoid collisions, reserved names (`admin`, `root`, etc.) get a suffix (e.g., `admin1`). User is created with `primary_group: adm`, `groups: [sudo]`, `no_user_group: true` -- systemd service runs as that user: - - `coder-agent.service` - -## Troubleshooting quick hits - -- iPXE boot loop: ensure template has bootable root disk and boot order `scsi0,ide2,net0` -- QGA not responding: install/enable QGA in template; allow 60–120s on first boot -- Snippet upload errors: storage must include `Snippets`; token needs Datastore permissions; path format `:snippets/` handled by provider -- Permissions errors: ensure the token's role covers the target node(s) and storages -- Verify snippet/QGA: `qm config | egrep 'cicustom|ide2|ciuser'` - -## References - -- Ubuntu Cloud Images (latest): https://cloud-images.ubuntu.com/ ([source](https://cloud-images.ubuntu.com/)) -- Proxmox qm(1) manual: https://pve.proxmox.com/pve-docs/qm.1.html -- Proxmox Cloud‑Init Support: https://pve.proxmox.com/wiki/Cloud-Init_Support -- Terraform Proxmox provider (bpg): `bpg/proxmox` on the Terraform Registry -- Coder – Best practices & templates: - - https://coder.com/docs/tutorials/best-practices/speed-up-templates - - https://coder.com/docs/tutorials/template-from-scratch \ No newline at end of file diff --git a/coder/proxmox-vm/cloud-init/user-data.tftpl b/coder/proxmox-vm/cloud-init/user-data.tftpl deleted file mode 100644 index 2cd34d0..0000000 --- a/coder/proxmox-vm/cloud-init/user-data.tftpl +++ /dev/null @@ -1,53 +0,0 @@ -#cloud-config -hostname: ${hostname} - -users: - - name: ${linux_user} - groups: [sudo] - shell: /bin/bash - sudo: ["ALL=(ALL) NOPASSWD:ALL"] - -package_update: false -package_upgrade: false -packages: - - curl - - ca-certificates - - git - - jq - -write_files: - - path: /opt/coder/init.sh - permissions: "0755" - owner: root:root - encoding: b64 - content: | - ${coder_init_script_b64} - - - path: /etc/systemd/system/coder-agent.service - permissions: "0644" - owner: root:root - content: | - [Unit] - Description=Coder Agent - Wants=network-online.target - After=network-online.target - - [Service] - Type=simple - User=${linux_user} - WorkingDirectory=/home/${linux_user} - Environment=HOME=/home/${linux_user} - Environment=CODER_AGENT_TOKEN=${coder_token} - ExecStart=/opt/coder/init.sh - OOMScoreAdjust=-1000 - Restart=always - RestartSec=5 - - [Install] - WantedBy=multi-user.target - -runcmd: - - systemctl daemon-reload - - systemctl enable --now coder-agent.service - -final_message: "Cloud-init complete on ${hostname}" \ No newline at end of file diff --git a/coder/proxmox-vm/main.tf b/coder/proxmox-vm/main.tf deleted file mode 100644 index 86da81b..0000000 --- a/coder/proxmox-vm/main.tf +++ /dev/null @@ -1,283 +0,0 @@ -terraform { - required_providers { - coder = { - source = "coder/coder" - } - proxmox = { - source = "bpg/proxmox" - } - } -} - -provider "coder" {} - -provider "proxmox" { - endpoint = var.proxmox_api_url - api_token = "${var.proxmox_api_token_id}=${var.proxmox_api_token_secret}" - insecure = true - - # SSH is needed for file uploads to Proxmox - ssh { - username = var.proxmox_ssh_user - password = var.proxmox_password - - node { - name = var.proxmox_node - address = var.proxmox_host - } - } -} - -variable "proxmox_api_url" { - type = string -} - -variable "proxmox_api_token_id" { - type = string - sensitive = true -} - -variable "proxmox_api_token_secret" { - type = string - sensitive = true -} - - -variable "proxmox_host" { - description = "Proxmox node IP or DNS for SSH" - type = string -} - -variable "proxmox_password" { - description = "Proxmox password (used for SSH)" - type = string - sensitive = true -} - -variable "proxmox_ssh_user" { - description = "SSH username on Proxmox node" - type = string - default = "root" -} - -variable "proxmox_node" { - description = "Target Proxmox node" - type = string - default = "pve" -} -variable "disk_storage" { - description = "Disk storage (e.g., local-lvm)" - type = string - default = "local-lvm" -} - -variable "snippet_storage" { - description = "Storage with Snippets content" - type = string - default = "local" -} - -variable "bridge" { - description = "Bridge (e.g., vmbr0)" - type = string - default = "vmbr0" -} - -variable "vlan" { - description = "VLAN tag (0 none)" - type = number - default = 0 -} - -variable "clone_template_vmid" { - description = "VMID of the cloud-init base template to clone" - type = number -} - -data "coder_workspace" "me" {} -data "coder_workspace_owner" "me" {} - -data "coder_parameter" "cpu_cores" { - name = "cpu_cores" - display_name = "CPU Cores" - type = "number" - default = 2 - mutable = true -} - -data "coder_parameter" "memory_mb" { - name = "memory_mb" - display_name = "Memory (MB)" - type = "number" - default = 4096 - mutable = true -} - -data "coder_parameter" "disk_size_gb" { - name = "disk_size_gb" - display_name = "Disk Size (GB)" - type = "number" - default = 20 - mutable = true - validation { - min = 10 - max = 100 - monotonic = "increasing" - } -} - -resource "coder_agent" "dev" { - arch = "amd64" - os = "linux" - - env = { - GIT_AUTHOR_NAME = data.coder_workspace_owner.me.name - GIT_AUTHOR_EMAIL = data.coder_workspace_owner.me.email - } - - startup_script_behavior = "non-blocking" - startup_script = <<-EOT - set -e - # Add any startup scripts here - EOT - - metadata { - display_name = "CPU Usage" - key = "cpu_usage" - script = "coder stat cpu" - interval = 10 - timeout = 1 - order = 1 - } - - metadata { - display_name = "RAM Usage" - key = "ram_usage" - script = "coder stat mem" - interval = 10 - timeout = 1 - order = 2 - } - - metadata { - display_name = "Disk Usage" - key = "disk_usage" - script = "coder stat disk" - interval = 600 - timeout = 30 - order = 3 - } -} - -locals { - hostname = lower(data.coder_workspace.me.name) - vm_name = "coder-${lower(data.coder_workspace_owner.me.name)}-${local.hostname}" - snippet_filename = "${local.vm_name}.yml" - base_user = replace(replace(replace(lower(data.coder_workspace_owner.me.name), " ", "-"), "/", "-"), "@", "-") # to avoid special characters in the username - linux_user = contains(["root", "admin", "daemon", "bin", "sys"], local.base_user) ? "${local.base_user}1" : local.base_user # to avoid conflict with system users - - rendered_user_data = templatefile("${path.module}/cloud-init/user-data.tftpl", { - coder_token = coder_agent.dev.token - coder_init_script_b64 = base64encode(coder_agent.dev.init_script) - hostname = local.vm_name - linux_user = local.linux_user - }) -} - -resource "proxmox_virtual_environment_file" "cloud_init_user_data" { - content_type = "snippets" - datastore_id = var.snippet_storage - node_name = var.proxmox_node - - source_raw { - data = local.rendered_user_data - file_name = local.snippet_filename - } -} - -resource "proxmox_virtual_environment_vm" "workspace" { - name = local.vm_name - node_name = var.proxmox_node - - clone { - node_name = var.proxmox_node - vm_id = var.clone_template_vmid - full = false - retries = 5 - } - - agent { - enabled = true - } - - on_boot = true - started = true - - startup { - order = 1 - } - - scsi_hardware = "virtio-scsi-pci" - boot_order = ["scsi0", "ide2"] - - memory { - dedicated = data.coder_parameter.memory_mb.value - } - - cpu { - cores = data.coder_parameter.cpu_cores.value - sockets = 1 - type = "host" - } - - network_device { - bridge = var.bridge - model = "virtio" - vlan_id = var.vlan == 0 ? null : var.vlan - } - - vga { - type = "serial0" - } - - serial_device { - device = "socket" - } - - disk { - interface = "scsi0" - datastore_id = var.disk_storage - size = data.coder_parameter.disk_size_gb.value - } - - initialization { - type = "nocloud" - datastore_id = var.disk_storage - - user_data_file_id = proxmox_virtual_environment_file.cloud_init_user_data.id - - ip_config { - ipv4 { - address = "dhcp" - } - } - } - - tags = ["coder", "workspace", local.vm_name] - - depends_on = [proxmox_virtual_environment_file.cloud_init_user_data] -} - -module "code-server" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder/code-server/coder" - version = "1.3.1" - agent_id = coder_agent.dev.id -} - -module "cursor" { - count = data.coder_workspace.me.start_count - source = "registry.coder.com/coder/cursor/coder" - version = "1.3.0" - agent_id = coder_agent.dev.id -} \ No newline at end of file diff --git a/coder/proxmox-vm/terraform.tfvars b/coder/proxmox-vm/terraform.tfvars deleted file mode 100644 index e854b72..0000000 --- a/coder/proxmox-vm/terraform.tfvars +++ /dev/null @@ -1,17 +0,0 @@ -# Proxmox API -proxmox_api_url = "https://:8006/api2/json" -proxmox_api_token_id = "!" -proxmox_api_token_secret = "" - -# SSH to the node (for snippet upload) -proxmox_host = "" -proxmox_password = "" -proxmox_ssh_user = "root" - -# Infra defaults -proxmox_node = "pve" -disk_storage = "local-lvm" -snippet_storage = "local" -bridge = "vmbr0" -vlan = 0 -clone_template_vmid = 999 \ No newline at end of file diff --git a/komodo/automate/coder/.env.sample b/komodo/automate/coder/.env.sample deleted file mode 100644 index 3d61b78..0000000 --- a/komodo/automate/coder/.env.sample +++ /dev/null @@ -1,11 +0,0 @@ -POSTGRES_USER=coder -POSTGRES_PASSWORD=password -POSTGRES_DB=coder -CODER_ACCESS_URL=coder.example.com - -CODER_OIDC_ISSUER_URL="https://auth.example.com/application/o/coder" -CODER_OIDC_EMAIL_DOMAIN="${CODER_OIDC_EMAIL_DOMAIN}" -CODER_OIDC_CLIENT_ID="${CODER_OIDC_CLIENT_ID}" -CODER_OIDC_CLIENT_SECRET="${CODER_OIDC_CLIENT_SECRET}" -CODER_OIDC_IGNORE_EMAIL_VERIFIED=true -CODER_OIDC_SIGN_IN_TEXT="Sign in with Authentik" \ No newline at end of file diff --git a/komodo/automate/coder/compose.yaml b/komodo/automate/coder/compose.yaml deleted file mode 100644 index c323af6..0000000 --- a/komodo/automate/coder/compose.yaml +++ /dev/null @@ -1,65 +0,0 @@ -services: - coder: - # This MUST be stable for our documentation and - # other automations. - image: ${CODER_REPO:-ghcr.io/coder/coder}:${CODER_VERSION:-latest} - ports: - - "7080:7080" - environment: - CODER_PG_CONNECTION_URL: "postgresql://${POSTGRES_USER:-username}:${POSTGRES_PASSWORD:-password}@database/${POSTGRES_DB:-coder}?sslmode=disable" - CODER_HTTP_ADDRESS: "0.0.0.0:7080" - # You'll need to set CODER_ACCESS_URL to an IP or domain - # that workspaces can reach. This cannot be localhost - # or 127.0.0.1 for non-Docker templates! - CODER_ACCESS_URL: "${CODER_ACCESS_URL}" - - # OpenID connect config - CODER_OIDC_ISSUER_URL: "${CODER_OIDC_ISSUER_URL}" - #CODER_OIDC_EMAIL_DOMAIN: "${CODER_OIDC_EMAIL_DOMAIN}" - CODER_OIDC_CLIENT_ID: "${CODER_OIDC_CLIENT_ID}" - CODER_OIDC_CLIENT_SECRET: "${CODER_OIDC_CLIENT_SECRET}" - CODER_OIDC_IGNORE_EMAIL_VERIFIED: true - CODER_OIDC_SIGN_IN_TEXT: "Sign in with Authentik" - CODER_OIDC_ICON_URL: https://authentik.company/static/dist/assets/icons/icon.png - CODER_OIDC_SCOPES: openid,profile,email,offline_access - - # If the coder user does not have write permissions on - # the docker socket, you can uncomment the following - # lines and set the group ID to one that has write - # permissions on the docker socket. - group_add: - - "988" # docker group on host - volumes: - - /var/run/docker.sock:/var/run/docker.sock - # Run "docker volume rm coder_coder_home" to reset the dev tunnel url (https://abc.xyz.try.coder.app). - # This volume is not required in a production environment - you may safely remove it. - # Coder can recreate all the files it needs on restart. - - coder_home:/home/coder - depends_on: - database: - condition: service_healthy - database: - # Minimum supported version is 13. - # More versions here: https://hub.docker.com/_/postgres - image: "postgres:17" - # Uncomment the next two lines to allow connections to the database from outside the server. - #ports: - # - "5432:5432" - environment: - POSTGRES_USER: ${POSTGRES_USER:-username} # The PostgreSQL user (useful to connect to the database) - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password} # The PostgreSQL password (useful to connect to the database) - POSTGRES_DB: ${POSTGRES_DB:-coder} # The PostgreSQL default database (automatically created at first launch) - volumes: - - coder_data:/var/lib/postgresql/data # Use "docker volume rm coder_coder_data" to reset Coder - healthcheck: - test: - [ - "CMD-SHELL", - "pg_isready -U ${POSTGRES_USER:-username} -d ${POSTGRES_DB:-coder}", - ] - interval: 5s - timeout: 5s - retries: 5 -volumes: - coder_data: - coder_home: \ No newline at end of file diff --git a/talos/README.md b/talos/README.md index 67910ae..0c67533 100644 --- a/talos/README.md +++ b/talos/README.md @@ -110,3 +110,17 @@ kubectl -n kube-system get pods -l app.kubernetes.io/name=kube-vip-ds -o wide nc -vz 192.168.50.230 6443 ``` +## 9) Argo CD via DNS host (no port) + +Argo CD is exposed through Cilium Ingress with host: + +- `argo.noble.lab.pcenicni.dev` + +Ingress manifest: + +- `clusters/noble/bootstrap/argocd/argocd-ingress.yaml` + +After syncing manifests, create a Pi-hole DNS A record: + +- `argo.noble.lab.pcenicni.dev` -> `192.168.50.230` +