Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt

Use this file to discover all available pages before exploring further.

Try free on Pangolin Cloud

Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
This page covers the main Pangolin Kubernetes configuration options for Helm and Kustomize workflows. For exhaustive option coverage, refer to the chart resources:

README

values.yaml

values.schema.json

Version context

This page is aligned with the Pangolin Helm chart 0.1.0-alpha.0.
ItemValue
Chart version0.1.0-alpha.0
Pangolin app version1.18.2
Kubernetes version>=1.30.14-0
Gerbil image tag1.3.1
pangolin-kube-controller image tag0.1.0-alpha.1
Traefik image tagv3.6.15

Configuration sections

Deployment topology

Control how Pangolin components are deployed and integrated with Kubernetes.
deployment:
  type: controller
  mode: multi
  installTraefikController: false
  traefikNamespace: ""
Recommended production topology:
deployment:
  type: controller
  mode: multi
SettingDescription
deployment.type=controllerUses pangolin-kube-controller and Traefik CRDs. Recommended for Kubernetes deployments.
deployment.type=standaloneRuns an internal Traefik workload managed by this chart. Mainly useful for labs and self-contained deployments.
deployment.mode=multiRuns Pangolin, Gerbil, and controller/Traefik components as separate workloads. Recommended for production.
deployment.mode=singleRuns multiple components in one shared Pod. Useful only when you explicitly need a compact topology.
deployment.installTraefikController=trueInstalls the bundled Traefik dependency in controller mode.
deployment.traefikNamespaceNamespace where Traefik controller resources live. Defaults to the release namespace when empty.
In controller mode, Traefik CRDs and a Traefik controller must be available. You can install Traefik separately or enable the bundled Traefik dependency with deployment.installTraefikController=true.
If you enable the bundled Traefik dependency, put Traefik chart overrides under the traefikController key.
Namespace creation is controlled by the namespace block.
namespace:
  create: false
  name: ""
  labels: {}
  podSecurity:
    enforce: ""
    warn: ""
    audit: ""
Recommended pattern:
  1. Create the namespace manually.
  2. Apply the required labels and annotations.
  3. Install the chart into that namespace.
kubectl create namespace pangolin
Gerbil requires NET_ADMIN for WireGuard interface management. If your cluster enforces Pod Security Admission, the namespace must allow that capability.Example:
kubectl label namespace pangolin \
  pod-security.kubernetes.io/enforce=privileged \
  --overwrite
If you let the chart create the namespace, configure the Pod Security labels through values:
namespace:
  create: true
  name: pangolin
  podSecurity:
    enforce: privileged
    warn: baseline
    audit: restricted
Do not apply a restricted Pod Security profile to a namespace running Gerbil unless you have validated WireGuard functionality. Gerbil requires NET_ADMIN; removing it breaks tunnel management.
Choose the database backend for Pangolin.
database:
  mode: cloudnativepg
  name: pangolin
  username: pangolin
Supported modes:
ModeUse case
cloudnativepgRecommended production mode using CloudNativePG. This is the default.
externalProduction mode with an externally managed PostgreSQL database.
embeddedChart-managed PostgreSQL for labs and test environments.
sqliteDevelopment or CI only. Not recommended for production.

CloudNativePG

The default database mode is cloudnativepg.
database:
  mode: cloudnativepg
  cloudnativepg:
    cluster:
      name: pangolin-db
    connection:
      database: pangolin
      username: pangolin
      sslMode: disable

cnpg-operator:
  enabled: false

cnpg-cluster:
  enabled: false
  fullnameOverride: pangolin-db
CloudNativePG can be used in four common ways:
ModeValues
Existing operator and existing clustercnpg-operator.enabled=false, cnpg-cluster.enabled=false
Chart installs operator onlycnpg-operator.enabled=true, cnpg-cluster.enabled=false
Chart installs cluster onlycnpg-operator.enabled=false, cnpg-cluster.enabled=true
Chart installs operator and clustercnpg-operator.enabled=true, cnpg-cluster.enabled=true
When cnpg-cluster.enabled=true, keep the CNPG cluster name consistent:
database:
  cloudnativepg:
    cluster:
      name: pangolin-db

cnpg-cluster:
  enabled: true
  fullnameOverride: pangolin-db
For the default CNPG cluster name pangolin-db, CloudNativePG creates an application Secret named pangolin-db-app with the key uri. The chart can automatically use this default Secret when no explicit database.connection.existingSecretName is set.Explicit Secret reference:
database:
  connection:
    existingSecretName: pangolin-db-app
    existingSecretKey: uri

External PostgreSQL

For an external PostgreSQL database, prefer a Kubernetes Secret containing the final connection string.
database:
  mode: external
  connection:
    existingSecretName: pangolin-db-connection
    existingSecretKey: connectionString
The Secret should contain a PostgreSQL connection string:
kubectl create secret generic pangolin-db-connection \
  --namespace pangolin \
  --from-literal=connectionString='postgresql://pangolin:password@postgres.example.com:5432/pangolin?sslmode=require'
You can also let the chart create a connection Secret from values:
database:
  mode: external
  external:
    generatedSecret:
      create: true
      host: postgres.example.com
      port: 5432
      database: pangolin
      username: pangolin
      password: "<password>"
      sslMode: require
Avoid storing database passwords directly in values files for production. Use an existing Secret or your normal secret-management workflow.

Embedded PostgreSQL

Embedded PostgreSQL is intended for labs and tests.
database:
  mode: embedded
  embedded:
    persistence:
      enabled: true
      size: 8Gi

SQLite

SQLite is only suitable for development, CI, or very small test deployments.
database:
  mode: sqlite
  sqlite:
    persistence:
      enabled: true
      size: 1Gi
The pangolin.config block renders /app/config/config.yml.
pangolin:
  config:
    app:
      dashboard_url: "https://pangolin.example.com"
      log_level: info
    domains:
      domain1:
        base_domain: "example.com"
        cert_resolver: "letsencrypt"
    gerbil:
      start_port: 51820
      clients_start_port: 21820
      base_endpoint: "pangolin.example.com"
      use_subdomain: false
    traefik:
      enabled: true
      http_entrypoint: web
      https_entrypoint: websecure
      cert_resolver: letsencrypt
Important settings:
SettingDescription
pangolin.config.app.dashboard_urlPublic dashboard URL. Set this to the real user-facing URL.
pangolin.config.domainsDomain map used by Pangolin. Replace the default example.com entry before production use.
pangolin.config.gerbil.base_endpointPublic hostname or IP where Gerbil is reachable.
pangolin.config.gerbil.start_portFirst WireGuard site port. Keep this aligned with gerbil.ports.wg1.
pangolin.config.gerbil.clients_start_portClient WireGuard port. Keep this aligned with gerbil.ports.wg2.
pangolin.config.traefik.enabledIncludes Pangolin’s Traefik config section. This does not install Traefik.
pangolin.config.traefik.cert_resolverACME resolver name used in Pangolin-generated Traefik configuration.
pangolin.config.traefik controls the Traefik configuration generated by Pangolin. Traefik installation is controlled separately through controller mode, the bundled Traefik dependency, or standalone Traefik mode.

Pangolin app secret

Pangolin requires SERVER_SECRET.Use an existing Secret for production:
pangolin:
  secret:
    existingSecretName: pangolin-app-secret
    existingSecretKey: SERVER_SECRET
Create the Secret:
kubectl create secret generic pangolin-app-secret \
  --namespace pangolin \
  --from-literal=SERVER_SECRET='<strong-random-secret>'
If no existing Secret is provided, the chart can generate one:
pangolin:
  secret:
    generated:
      create: true
      key: SERVER_SECRET
      length: 64
Do not commit plaintext secrets to Git. For GitOps workflows, use SOPS, Sealed Secrets, External Secrets Operator, Vault, Infisical, or a cloud secret manager.
In controller mode, the chart can render a Traefik IngressRoute for the Pangolin dashboard and API.
pangolin:
  ingressRoute:
    dashboard:
      enabled: true
      host: ""
      ingressClassName: ""
      traefikSelectorLabels: {}
      entryPoints:
        - websecure
      routes:
        api:
          enabled: true
          pathPrefix: /api/v1
          priority: 100
        dashboard:
          enabled: true
          priority: 10
      tls:
        enabled: true
        certResolver: ""
        secretName: ""
Default routing behavior:
RouteMatchBackend port
APIHost(...) && PathPrefix(/api/v1)pangolin.service.ports.external, default 3000
DashboardHost(...)pangolin.service.ports.next, default 3002
The host defaults to the hostname from pangolin.config.app.dashboard_url. You can override it with:
pangolin:
  ingressRoute:
    dashboard:
      host: pangolin.example.com

TLS with certResolver

pangolin:
  config:
    traefik:
      cert_resolver: letsencrypt
  ingressRoute:
    dashboard:
      tls:
        enabled: true
        certResolver: letsencrypt
        secretName: ""

TLS with existing Secret

pangolin:
  ingressRoute:
    dashboard:
      tls:
        enabled: true
        certResolver: ""
        secretName: pangolin-dashboard-tls
tls.certResolver and tls.secretName are mutually exclusive. Use one or the other.

Multi-Traefik setups

Use labels to target a specific Traefik CRD provider when multiple Traefik instances watch different label selectors:
pangolin:
  ingressRoute:
    dashboard:
      traefikSelectorLabels:
        traefik-instance: public
You can also set an ingress class annotation:
pangolin:
  ingressRoute:
    dashboard:
      ingressClassName: traefik-public
Gerbil manages WireGuard tunnel connectivity for Pangolin.
gerbil:
  enabled: true
  startupMode: normal
  ports:
    wg1: 51820
    wg2: 21820
    internalApi: 3004
  service:
    enabled: true
    type: ClusterIP
  persistence:
    enabled: true
    size: 1Gi
Important settings:
SettingDescription
gerbil.enabledEnables the Gerbil component.
gerbil.startupModeControls first-run and normal startup behavior.
gerbil.ports.wg1First WireGuard UDP port. Keep aligned with pangolin.config.gerbil.start_port.
gerbil.ports.wg2Second WireGuard UDP port. Keep aligned with pangolin.config.gerbil.clients_start_port.
gerbil.ports.internalApiInternal Gerbil API/listener port.
gerbil.service.enabledCreates a Service for Gerbil UDP traffic.
gerbil.persistence.enabledPersists Gerbil key/config data. Recommended for production.
If Gerbil is exposed through a reverse proxy or UDP gateway, keep proxy protocol settings aligned end-to-end. Do not enable proxy protocol on the upstream hop unless Gerbil is configured to accept it.

Startup mode

gerbil:
  startupMode: delayed
ModeBehavior
normalStarts Gerbil immediately. Use after Pangolin setup is complete.
delayedRenders Gerbil resources but keeps the Deployment at replicas: 0 in multi mode. Useful for first installs and smoke tests.
disabledUntilSetupDoes not render Gerbil resources until switched back to normal or delayed.
For first installs, delayed can help when Gerbil would otherwise fail before the initial Pangolin setup is complete.Switch back after setup:
helm upgrade pangolin fossorial/pangolin \
  --namespace pangolin \
  --reuse-values \
  --set gerbil.startupMode=normal

Security

Gerbil requires NET_ADMIN.
gerbil:
  securityContext:
    runAsNonRoot: false
    allowPrivilegeEscalation: false
    readOnlyRootFilesystem: false
    capabilities:
      add:
        - NET_ADMIN
      drop:
        - ALL
Do not remove NET_ADMIN from Gerbil. Without it, Gerbil cannot create or manage WireGuard interfaces. SYS_MODULE is not added by default and should only be added when your node kernel requires module loading from inside the container.
NetworkPolicy rendering is enabled by default.
The chart-managed NetworkPolicies are intended to allow required Pangolin, Gerbil, database, DNS, and controller traffic for standard deployments.
networkPolicy:
  enabled: true
  allowExternalIngress: true
  allowExternalEgressHttps: false
  dns:
    enabled: true
  database:
    enabled: true
    port: 5432
  controller:
    egress:
      enabled: true
      kubernetesApi:
        enabled: true
        cidr: ""
        port: 443
    metrics:
      enabled: false
  gerbil:
    allowWireguardUdpEgress: true
    wireguardUdpCIDRs:
      - 0.0.0.0/0
Important defaults:
SettingDefaultNotes
networkPolicy.enabledtrueRenders NetworkPolicy resources.
networkPolicy.allowExternalIngresstrueAllows public ingress to exposed services controlled by the chart.
networkPolicy.allowExternalEgressHttpsfalseBroad HTTPS egress is not allowed by default. Prefer scoped extraEgress rules.
networkPolicy.dns.enabledtrueAllows DNS egress.
networkPolicy.database.enabledtrueAdds database egress rules for Pangolin.
networkPolicy.controller.egress.kubernetesApi.enabledtrueAllows controller API-server access when configured.
networkPolicy.gerbil.allowWireguardUdpEgresstrueAllows Gerbil UDP egress for WireGuard peer traffic.
When tightening policies, verify these paths:
  • DNS egress
  • Pangolin to database
  • controller to Kubernetes API
  • ingress controller to Pangolin service
  • Gerbil UDP traffic
  • outbound access for SMTP, OIDC, webhooks, or other external integrations
Use component-scoped rules where possible:
networkPolicy:
  pangolin:
    extraEgress: []
  controller:
    extraEgress: []
  gerbil:
    extraEgress: []
If you disable or replace chart-managed NetworkPolicies, ensure your custom policies still allow all required traffic paths.
The chart has chart-level monitoring settings for Pangolin and controller-specific monitoring settings for pangolin-kube-controller.

Pangolin monitoring

monitoring:
  enabled: false
  service:
    enabled: false
    type: ClusterIP
    port: 9090
    portName: metrics
  metrics:
    targetPortName: metrics
    targetPort: 9090
    path: /metrics

Controller monitoring

controller:
  service:
    enabled: true
    port: 9090
    portName: metrics
  monitoring:
    serviceMonitor:
      enabled: false
    podMonitor:
      enabled: false
    prometheusRule:
      enabled: false
Enable controller ServiceMonitor when Prometheus Operator is available:
controller:
  monitoring:
    serviceMonitor:
      enabled: true
Enable chart-level metrics Service when the Pangolin app exposes metrics in your selected configuration:
monitoring:
  enabled: true
  service:
    enabled: true
Only enable ServiceMonitor, PodMonitor, or PrometheusRule resources when the matching CRDs are installed in the cluster.
The chart uses separate ServiceAccounts for Pangolin, Gerbil, and the controller in multi mode.
serviceAccount:
  pangolin:
    create: true
    automountServiceAccountToken: false
  gerbil:
    create: true
    automountServiceAccountToken: false
  controller:
    create: true
    automountServiceAccountToken: true

rbac:
  create: true
Default behavior:
ComponentAPI token mounted by defaultReason
PangolinNoThe app does not need Kubernetes API access.
GerbilNoGerbil manages WireGuard and does not need Kubernetes API access.
ControllerYesThe controller reconciles Traefik CRDs and needs Kubernetes API access.
In deployment.mode=single with deployment.type=controller, Kubernetes ServiceAccount selection is Pod-level. The shared Pod uses the controller ServiceAccount and token.
Global scheduling defaults:
global:
  storageClass: ""
  image:
    registry: docker.io
    imagePullPolicy: IfNotPresent
    imagePullSecrets: []
  nodeSelector: {}
  tolerations: []
  affinity: {}
  topologySpreadConstraints: []
  priorityClassName: ""
Resource rendering policy:
resourcesPolicy:
  cpuLimits:
    enabled: true
  ephemeralStorage:
    enabled: false
CPU limits can cause throttling even when spare CPU exists on the node. For most deployments, start with CPU requests and memory limits, then add CPU limits only when explicitly required.
Pangolin resources:
pangolin:
  resources:
    requests:
      cpu: 200m
      memory: 256Mi
      ephemeral-storage: 32Mi
    limits:
      cpu: 1000m
      memory: 1Gi
      ephemeral-storage: 256Mi
Gerbil resources:
gerbil:
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
      ephemeral-storage: 16Mi
    limits:
      cpu: 500m
      memory: 512Mi
      ephemeral-storage: 128Mi
Controller resources:
controller:
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
      ephemeral-storage: 16Mi
    limits:
      cpu: 500m
      memory: 512Mi
      ephemeral-storage: 128Mi
Image configuration:
images:
  pangolin:
    registry: docker.io
    repository: fosrl/pangolin
    tag: ""
    digest: ""
  pangolinPostgresql:
    registry: docker.io
    repository: fosrl/pangolin
    tag: ""
    digest: ""
  gerbil:
    registry: docker.io
    repository: fosrl/gerbil
    tag: "1.3.1"
    digest: ""
  controller:
    registry: ghcr.io
    repository: fosrl/pangolin-kube-controller
    tag: "0.1.0-alpha.1"
    digest: ""
  traefik:
    registry: docker.io
    repository: traefik
    tag: v3.6.15
    digest: ""
The chart automatically selects the PostgreSQL-capable Pangolin image variant for non-SQLite database modes unless you override the Pangolin tag or digest.
Ephemeral-storage requests and limits are only rendered when resourcesPolicy.ephemeralStorage.enabled=true.
Standalone Traefik is used mainly when deployment.type=standalone.
traefik:
  enabled: false
  service:
    enabled: true
    type: LoadBalancer
  config:
    dashboard: false
    httpEntrypoint: web
    httpsEntrypoint: websecure
    certResolver: letsencrypt
    letsencryptEmail: ""
  persistence:
    enabled: false
Important notes:
  • traefik.enabled=true runs an internal Traefik workload managed by this chart.
  • traefik.config.letsencryptEmail is required when standalone Traefik is enabled.
  • If you enable the Traefik dashboard, enable traefik.persistence.enabled so ACME state survives restarts.
  • In controller mode, prefer using an existing or bundled Traefik controller instead of standalone Traefik.
The chart can store Pangolin Blueprint YAML files as Kubernetes ConfigMaps and Secrets.
pangolin:
  blueprints:
    enabled: false
    configMap:
      create: true
    files: {}
    environmentSecret:
      create: true
    existingConfigMap: ""
    existingEnvironmentSecret: ""
Example:
pangolin:
  blueprints:
    enabled: true
    configMap:
      create: true
    files:
      site-blueprint.yaml: |
        sites:
          my-site:
            name: My Site
        public-resources:
          web-app:
            name: Web Application
            protocol: http
            full-domain: "app.example.com"
            targets:
              - site: my-site
                hostname: app
                port: 8080
                method: http
Sensitive blueprint environment values should come from a Secret:
pangolin:
  blueprints:
    enabled: true
    existingConfigMap: my-blueprint-configmap
    existingEnvironmentSecret: my-blueprint-env
The Pangolin server does not apply Blueprint files directly. Blueprints are applied by Newt through the Pangolin API using --blueprint-file or --provisioning-blueprint-file.

Configuration by install method

Helm

Use a values file:
helm upgrade --install pangolin fossorial/pangolin \
  --namespace pangolin \
  --values values-pangolin.yaml
Use inline values only for small tests:
helm upgrade --install pangolin fossorial/pangolin \
  --namespace pangolin \
  --set deployment.type=controller \
  --set deployment.mode=multi \
  --set database.mode=cloudnativepg \
  --set pangolin.config.app.dashboard_url=https://pangolin.example.com
See Pangolin Helm for the installation flow. For complete application configuration keys and examples, see:

Kustomize

Render the chart with Helm, then apply Kustomize overlays:
helm template pangolin fossorial/pangolin \
  --namespace pangolin \
  --values values-pangolin.yaml \
  > base/pangolin.yaml
Apply the overlay:
kubectl apply -k overlays/prod
See Pangolin Kustomize for the Kustomize workflow.

GitOps

Store Helm values or Kustomize overlays in Git. Argo CD or Flux reconciles the desired state. Argo CD Helm example:
spec:
  source:
    helm:
      values: |
        deployment:
          type: controller
          mode: multi
        database:
          mode: cloudnativepg
Flux HelmRelease example:
spec:
  values:
    deployment:
      type: controller
      mode: multi
    database:
      mode: cloudnativepg
See GitOps for GitOps guidance.

Next steps

Helm Install

Install Pangolin with Helm.

Kustomize Install

Install Pangolin with rendered manifests and Kustomize overlays.

Troubleshooting

Debug Pangolin deployments on Kubernetes.

GitOps

Deploy Pangolin with Argo CD or Flux.