Troubleshooting
Diagnose and resolve common Newt Kubernetes deployment issues.
Use this guide to troubleshoot Newt Kubernetes deployments installed with Helm, Kustomize, Argo CD, or Flux.
Start with the basic checks, then move to the section that matches the symptom.
Quick checks
Set the namespace and release name used by your installation:
export NEWT_NAMESPACE=pangolin
export NEWT_RELEASE=newtCheck the Helm release:
helm status "$NEWT_RELEASE" --namespace "$NEWT_NAMESPACE"
helm history "$NEWT_RELEASE" --namespace "$NEWT_NAMESPACE"Check Newt pods:
kubectl get pods --namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newtCheck recent events:
kubectl get events --namespace "$NEWT_NAMESPACE" \
--sort-by=.lastTimestampCheck logs:
kubectl logs --namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newt \
--tail=100Check the applied Helm values:
helm get values "$NEWT_RELEASE" --namespace "$NEWT_NAMESPACE"Do not assume the pod or Deployment name. Chart-generated names can change with the Helm release name, instance name, nameOverride, or fullnameOverride.
Get the generated resource names
List Newt resources:
kubectl get deploy,sts,svc,secret,cm --namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newtList pods with labels:
kubectl get pods --namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newt \
--show-labelsStore the first Newt pod name:
export NEWT_POD="$(kubectl get pod --namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newt \
-o jsonpath='{.items[0].metadata.name}')"Then use:
echo "$NEWT_POD"Pod fails to start
Symptoms
STATUS RESTARTS
CrashLoopBackOff 5
Error 3
CreateContainerConfigError
ImagePullBackOffCheck pod details
kubectl describe pod "$NEWT_POD" --namespace "$NEWT_NAMESPACE"Check logs:
kubectl logs "$NEWT_POD" --namespace "$NEWT_NAMESPACE" --tail=100If the container restarts quickly, check the previous logs:
kubectl logs "$NEWT_POD" --namespace "$NEWT_NAMESPACE" --previous --tail=100Common causes
| Symptom | Likely cause | Check |
|---|---|---|
Secret "..." not found | Secret name does not match auth.existingSecretName | kubectl get secret -n "$NEWT_NAMESPACE" |
| Missing env var or empty credential | Secret exists but key names do not match auth.keys.* | kubectl describe secret <secret> -n "$NEWT_NAMESPACE" |
| Authentication failure | Wrong NEWT_ID, NEWT_SECRET, or provisioning key | Check credentials in Pangolin |
| Endpoint connection errors | PANGOLIN_ENDPOINT is wrong or unreachable | Test DNS and HTTPS from the pod |
| Image pull failure | Registry or image settings are wrong | kubectl describe pod |
Secret issues
Verify the Secret exists
kubectl get secret newt-auth --namespace "$NEWT_NAMESPACE"Check Secret keys
kubectl describe secret newt-auth --namespace "$NEWT_NAMESPACE"The default keys are:
PANGOLIN_ENDPOINT
NEWT_ID
NEWT_SECRETIf your Secret uses different key names, map them in values:
newtInstances:
- name: main-tunnel
enabled: true
auth:
existingSecretName: newt-auth
keys:
endpointKey: PANGOLIN_ENDPOINT
idKey: NEWT_ID
secretKey: NEWT_SECRETDo not paste decoded secrets into issue reports, logs, screenshots, or public repositories.
Check which Secret the pod uses
kubectl get pod "$NEWT_POD" --namespace "$NEWT_NAMESPACE" \
-o jsonpath='{range .spec.containers[*].envFrom[*]}{.secretRef.name}{"\n"}{end}'Also inspect explicit Secret references:
kubectl get pod "$NEWT_POD" --namespace "$NEWT_NAMESPACE" -o yaml | grep -A5 -B2 secretKeyRefNewt cannot reach Pangolin
Test DNS from the Newt pod
kubectl exec "$NEWT_POD" --namespace "$NEWT_NAMESPACE" -- \
nslookup pangolin.example.comTest HTTPS from the Newt pod
kubectl exec "$NEWT_POD" --namespace "$NEWT_NAMESPACE" -- \
wget -S -O- https://pangolin.example.com 2>&1 | head -40Depending on the image, curl, wget, nc, or nslookup may not be available. If needed, run a temporary debug pod in the same namespace:
kubectl run net-debug \
--namespace "$NEWT_NAMESPACE" \
--rm -it \
--image=curlimages/curl:latest \
--restart=Never \
-- shThen test:
curl -vk https://pangolin.example.comCommon causes
| Problem | What to check |
|---|---|
| DNS fails | CoreDNS, NetworkPolicy egress to DNS, wrong hostname |
| HTTPS fails | ingress, TLS certificate, firewall, proxy, wrong endpoint |
| TLS verification fails | certificate chain, hostname mismatch, private CA |
| Works locally but not in cluster | egress policies, proxy settings, DNS split-horizon |
Newt pod is running but site is offline
Check logs:
kubectl logs "$NEWT_POD" --namespace "$NEWT_NAMESPACE" --tail=200Check the site in the Pangolin dashboard.
Verify:
- the site credentials belong to the same site
- the site was not deleted or regenerated in Pangolin
PANGOLIN_ENDPOINTpoints to the correct Pangolin URL- the cluster can resolve and reach the Pangolin endpoint
- outbound HTTPS is allowed from the Newt namespace
- the Secret is in the same namespace as the Newt workload
If you use provisioning, also verify:
provisioningKeyis validnewtNameis set as expectedconfigPersistence.enabled=true- the configured
CONFIG_FILEpath is writable
Provisioning issues
Provisioning requires writable config persistence.
Symptoms
- Newt starts but does not keep generated credentials after restart.
- Newt provisions repeatedly.
- Logs mention config file or write errors.
- Pod restarts cause the site to appear as a new or unconfigured instance.
Check values
helm get values "$NEWT_RELEASE" --namespace "$NEWT_NAMESPACE"Provisioning example:
newtInstances:
- name: main-tunnel
enabled: true
auth:
pangolinEndpoint: https://pangolin.example.com
provisioningKey: "<provisioning-key>"
newtName: "my-site"
configPersistence:
enabled: true
type: emptyDir
mountPath: /var/lib/newt
fileName: config.jsonFor durable state, use an existing PVC:
newtInstances:
- name: main-tunnel
enabled: true
auth:
pangolinEndpoint: https://pangolin.example.com
provisioningKey: "<provisioning-key>"
newtName: "my-site"
configPersistence:
enabled: true
type: persistentVolumeClaim
existingClaim: my-newt-config
mountPath: /var/lib/newt
fileName: config.jsonemptyDir is recreated when the pod is recreated. Use a PVC if the generated configuration must survive pod replacement.
Service not created or not reachable
Important behavior
acceptClients does not create a Service.
A Service is created through:
newtInstances:
- name: main-tunnel
service:
enabled: trueThe chart also has service.enabledWhenAcceptClients, but runtime client behavior and Service rendering should still be verified in the rendered manifests.
Check Services
kubectl get svc --namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newtDescribe the Service:
kubectl describe svc <service-name> --namespace "$NEWT_NAMESPACE"LoadBalancer stuck in pending
EXTERNAL-IP <pending>Common causes:
- the cluster has no cloud load balancer integration
- bare-metal cluster without MetalLB or equivalent
- cloud provider quota or permission issue
- invalid
loadBalancerClass - invalid
loadBalancerSourceRanges
For bare-metal clusters, use MetalLB or another load balancer implementation, or use NodePort if appropriate.
Metrics scraping does not work
Metrics are disabled by default.
Enable metrics:
global:
metrics:
enabled: trueThe chart default admin address is:
global:
metrics:
adminAddr: ":2112"This listens on all interfaces and allows in-cluster scraping. Do not set it to 127.0.0.1:2112 if Prometheus scrapes from another pod.
Metrics Service
Enable the metrics Service:
global:
metrics:
enabled: true
service:
enabled: true
port: 2112ServiceMonitor
If you use Prometheus Operator:
global:
metrics:
enabled: true
service:
enabled: true
serviceMonitor:
enabled: trueCheck resources:
kubectl get svc,podmonitor,servicemonitor,prometheusrule \
--namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newtThe chart has separate metrics values for container port, admin address, and metrics Service port. Check the rendered manifest when changing these values.
NetworkPolicy blocks traffic
If NetworkPolicy is enabled, check that the policy allows required egress.
Newt usually needs egress to:
- DNS
- Pangolin endpoint over HTTPS
- any tunnel or connectivity endpoints used by your deployment
Check policies:
kubectl get networkpolicy --namespace "$NEWT_NAMESPACE"
kubectl describe networkpolicy --namespace "$NEWT_NAMESPACE"If DNS is blocked, enable or add DNS egress rules.
Example:
global:
networkPolicy:
enabled: true
components:
dns:
enabled: trueIf HTTPS egress is blocked, add an appropriate custom egress rule for your environment.
Multiple Newt instances conflict
Symptoms
- Multiple pods run, but only one site connects.
- Both instances use the same credentials.
- A site appears to flap between instances.
- Logs show authentication or registration conflicts.
Check values
helm get values "$NEWT_RELEASE" --namespace "$NEWT_NAMESPACE"Each instance should use its own credentials or provisioning identity:
newtInstances:
- name: site-a
enabled: true
auth:
existingSecretName: newt-auth-site-a
- name: site-b
enabled: true
auth:
existingSecretName: newt-auth-site-bCreate separate Secrets:
kubectl create secret generic newt-auth-site-a \
--namespace "$NEWT_NAMESPACE" \
--from-literal=PANGOLIN_ENDPOINT=https://pangolin.example.com \
--from-literal=NEWT_ID=<site-a-newt-id> \
--from-literal=NEWT_SECRET=<site-a-newt-secret>
kubectl create secret generic newt-auth-site-b \
--namespace "$NEWT_NAMESPACE" \
--from-literal=PANGOLIN_ENDPOINT=https://pangolin.example.com \
--from-literal=NEWT_ID=<site-b-newt-id> \
--from-literal=NEWT_SECRET=<site-b-newt-secret>RBAC or service account issues
Chart 1.4.0 disables RBAC creation by default.
Check service account and RBAC:
kubectl get serviceaccount,role,rolebinding \
--namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newtIf your configuration requires Kubernetes API access, enable RBAC:
rbac:
create: true
clusterRole: falseFor most Newt deployments, RBAC is not required.
High CPU or memory usage
Check resource usage:
kubectl top pod --namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newtCheck current resource settings:
kubectl get pod "$NEWT_POD" --namespace "$NEWT_NAMESPACE" \
-o jsonpath='{.spec.containers[0].resources}'Tune resources in values:
newtInstances:
- name: main-tunnel
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 512MiThen upgrade:
helm upgrade "$NEWT_RELEASE" fossorial/newt \
--namespace "$NEWT_NAMESPACE" \
--values values-newt.yamlCommon causes of high usage:
- high tunnel traffic
- too low resource limits
- repeated reconnect loops
- excessive debug logging
- MTU or network path issues
MTU issues
Symptoms
- Connections establish but large transfers fail.
- Some websites or services work, others hang.
- Logs show repeated reconnects.
- Throughput is much lower than expected.
Newt defaults to MTU 1280.
Try another MTU only after confirming basic connectivity:
newtInstances:
- name: main-tunnel
mtu: 1280Upgrade after changing values:
helm upgrade "$NEWT_RELEASE" fossorial/newt \
--namespace "$NEWT_NAMESPACE" \
--values values-newt.yamlHelm debugging
Preview an upgrade:
helm upgrade "$NEWT_RELEASE" fossorial/newt \
--namespace "$NEWT_NAMESPACE" \
--values values-newt.yaml \
--dry-runRender the chart locally:
helm template "$NEWT_RELEASE" fossorial/newt \
--namespace "$NEWT_NAMESPACE" \
--values values-newt.yamlShow rendered manifests from the live release:
helm get manifest "$NEWT_RELEASE" --namespace "$NEWT_NAMESPACE"Show values from the live release:
helm get values "$NEWT_RELEASE" --namespace "$NEWT_NAMESPACE"Rollback:
helm rollback "$NEWT_RELEASE" <revision> --namespace "$NEWT_NAMESPACE"Kustomize debugging
Validate the overlay:
kustomize build overlays/site-aRun a server-side dry run:
kustomize build overlays/site-a | kubectl apply -f - --dry-run=serverPreview live changes:
kustomize build overlays/site-a | kubectl diff -f -If a patch does not apply, inspect generated resource names:
kustomize build base | grep -E "^(kind:| name:)"Collect diagnostics
Collect logs and resource information:
kubectl logs --namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newt \
--tail=200 > newt-logs.txt
kubectl get pods --namespace "$NEWT_NAMESPACE" \
-l app.kubernetes.io/name=newt \
-o yaml > newt-pods.yaml
kubectl get events --namespace "$NEWT_NAMESPACE" \
--sort-by=.lastTimestamp > newt-events.txt
helm get values "$NEWT_RELEASE" \
--namespace "$NEWT_NAMESPACE" > newt-helm-values.yaml
helm get manifest "$NEWT_RELEASE" \
--namespace "$NEWT_NAMESPACE" > newt-helm-manifest.yamlIf using Kustomize:
kustomize build overlays/site-a > newt-kustomize-output.yamlBefore sharing diagnostics, remove:
- Newt credentials
- provisioning keys
- TLS private keys
- tokens
- passwords
- internal hostnames if sensitive
Next steps
Was this page helpful?

