variable "service_name" { description = "Service name" type = string default = "ilsp" } variable "image_tag" { description = "Docker image tag — override in CI: -var=\"image_tag=$SHA\"" type = string default = "latest" } job "ilsp" { region = "global" datacenters = ["dc1"] type = "service" meta { uuid = uuidv4() deployed_at = "[[ timeNowUTC ]]" } update { stagger = "30s" max_parallel = 1 auto_revert = true progress_deadline = "25m" } group "ilsp-group" { count = 1 constraint { attribute = "${node.unique.name}" value = "autobox.i80.dk" } update { canary = 1 auto_promote = true min_healthy_time = "15s" healthy_deadline = "20m" progress_deadline = "25m" auto_revert = true } # Single dynamic port — Traefik routes ilsp.i80.dk → this port. # Editors connect via WebSocket: ws://ilsp.i80.dk/python ws://ilsp.i80.dk/bicep # LSP servers (pylsp, Bicep LS) run on localhost inside the container only. network { port "http" {} } reschedule { attempts = 5 interval = "10m" delay = "30s" delay_function = "exponential" max_delay = "120s" unlimited = false } # Health check only — Traefik not used for LSP TCP traffic service { provider = "consul" name = var.service_name port = "http" tags = [ "traefik.enable=true", "traefik.http.routers.${var.service_name}.rule=Host(`${var.service_name}.i80.dk`)", "traefik.http.routers.${var.service_name}.tls=true", ] check { name = "health_http" type = "http" port = "http" path = "/health" interval = "15s" timeout = "5s" } } task "ilsp-task" { driver = "docker" config { image = "registry.i80.dk/gitea/ilsp:${var.image_tag}" ports = ["http"] force_pull = true auth { username = "robot$gitserver" password = "${HARBOR_ROBOT_TOKEN}" } } restart { attempts = 5 interval = "10m" delay = "30s" mode = "fail" } env { HTTP_PORT = "${NOMAD_PORT_http}" PYTHON_LSP_PORT = "2087" BICEP_LSP_PORT = "2088" DEVOPS_MCP_URL = "https://devops-mcp.i80.dk" PYTHONUNBUFFERED = "1" } # Secrets from Consul KV template { data = <