<p>I'm studying helm3 and k8s (microk8s).
While tryingi the following command:</p>
<pre><code>helm install traefik traefik/traefik  -n traefik --values traefik-values.yaml
</code></pre>
<p>and traefik-values.yaml has the following value:</p>
<pre><code>additionalArguments:
  - &quot;--certificatesresolvers.letsencrypt.acme.email=&lt;my-email&gt;&quot;
  - &quot;--certificatesresolvers.letsencrypt.acme.storage=/data/acme.json&quot;
  - &quot;--certificatesresolvers.letsencrypt.acme.caserver=https://acme-v02.api.letsencrypt.org/directory&quot;
  - &quot;--certificatesResolvers.letsencrypt.acme.tlschallenge=true&quot;
  - &quot;--api.insecure=true&quot;
  - &quot;--accesslog=true&quot;
  - &quot;--log.level=INFO&quot;
hostNetwork: true
ipaddress: &lt;my-ip&gt;
service:
  type: ClusterIP
ports:
  web:
    port: 80
  websecure:
    port: 443
</code></pre>
<p>I receive this bind-permission error</p>
<pre><code>traefik.go:76: command traefik error: error while building entryPoint web: error preparing server: error opening listener: listen tcp :80: bind: permission denied
</code></pre>
<p>on the other hand, I can install Traefik on the same ports (80 and 443) using the following <code>yaml</code> file (approximately the example on <a href="https://doc.traefik.io/traefik/v1.5/user-guide/kubernetes/" rel="nofollow noreferrer">Traefik's site</a>):</p>
<pre><code>---
apiVersion: v1
kind: Namespace
metadata:
  name: traefik
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller
  namespace: traefik
---
kind: DaemonSet
apiVersion: apps/v1
metadata:
  name: traefik-ingress-controller
  namespace: traefik
  labels:
    k8s-app: traefik-ingress-lb
spec:
  selector:
    matchLabels:
      k8s-app: traefik-ingress-lb
      name: traefik-ingress-lb
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      tolerations:
      - effect: NoSchedule
        operator: Exists
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      hostNetwork: true
      containers:
      - image: traefik:2.4
        name: traefik-ingress-lb
        ports:
        - name: http
          containerPort: 80
          hostPort: 80
        # - name: admin
        #   containerPort: 8080
        #   hostPort: 8080
        securityContext:
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE
        args:
        - --providers.kubernetesingress=true
        # you need to manually set this IP to the incoming public IP
        # that your ingress resources would use. Note it only affects
        # status and kubectl UI, and doesn't really do anything
        # It could even be left out https://github.com/containous/traefik/issues/6303
        - --providers.kubernetesingress.ingressendpoint.ip=&lt;my-server-ip&gt;
        ## uncomment these and the ports above and below to enable
        ## the web UI on the host NIC port 8080 in **insecure** mode
        - --api.dashboard=true
        - --api.insecure=true
        - --log=true
        - --log.level=INFO
        - --accesslog=true
        - --entrypoints.web.address=:80
        - --entrypoints.websecure.address=:443
        - --certificatesresolvers.leresolver.acme.tlschallenge=true # &lt;== Enable TLS-ALPN-01 to generate and renew ACME certs
        - --certificatesresolvers.leresolver.acme.email=&lt;email&gt; # &lt;== Setting email for certs
        - --certificatesresolvers.leresolver.acme.storage=/data/acme.json # &lt;== Defining acme file to store cert information
        
---
kind: Service
apiVersion: v1
metadata:
  name: traefik-ingress-service
  namespace: traefik
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
    - protocol: TCP
      port: 80
      name: web
    # - protocol: TCP
      # port: 8080
      # name: admin
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: traefik-ingress-controller
rules:
  - apiGroups:
      - &quot;&quot;
    resources:
      - services
      - endpoints
      - secrets
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - extensions
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: traefik-ingress-controller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
  name: traefik-ingress-controller
  namespace: traefik
</code></pre>
<p>The two specs are not identical but quite similar as far as I can understand. They both create a ServiceAccount in the 'traefik' namespace and grant a ClusterRole.</p>
<p>What part determines the permission on port 80?</p>

<p>There's an <a href="https://github.com/traefik/traefik-helm-chart/issues/336" rel="noreferrer">open issue</a> on the Traefik helm chart <a href="https://github.com/traefik/traefik-helm-chart/issues/336#issuecomment-776163841" rel="noreferrer">where Jasper Ben</a> suggests a working solution:</p>
<pre><code>hostNetwork: true
ports:
  web:
    port: 80
    redirectTo: websecure
  websecure:
    port: 443

securityContext:
  capabilities:
    drop: [ALL]
    add: [NET_BIND_SERVICE]
  readOnlyRootFilesystem: true
  runAsGroup: 0
  runAsNonRoot: false
  runAsUser: 0
</code></pre>
<p>The missing part in the helm chart is <code>NET_BIND_SERVICE</code> capability in the securityContext.</p>
