{"id":19865668,"url":"https://github.com/openfaas/ingress-operator","last_synced_at":"2025-12-16T00:15:09.920Z","repository":{"id":47202441,"uuid":"193486530","full_name":"openfaas/ingress-operator","owner":"openfaas","description":"Custom domains, paths and TLS for your OpenFaaS Functions","archived":false,"fork":false,"pushed_at":"2025-01-27T16:06:57.000Z","size":18454,"stargazers_count":69,"open_issues_count":10,"forks_count":23,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-30T11:09:44.724Z","etag":null,"topics":["faas","ingress","ingresscontroller","kubernetes","openfaas","operator","serverless"],"latest_commit_sha":null,"homepage":"https://docs.openfaas.com/reference/ssl/kubernetes-with-cert-manager/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openfaas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-24T10:44:56.000Z","updated_at":"2025-01-27T16:06:49.000Z","dependencies_parsed_at":"2025-02-28T20:13:06.641Z","dependency_job_id":"1d54b608-d1ef-4630-8c1f-3986da33d383","html_url":"https://github.com/openfaas/ingress-operator","commit_stats":null,"previous_names":["openfaas-incubator/ingress-operator"],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfaas%2Fingress-operator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfaas%2Fingress-operator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfaas%2Fingress-operator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openfaas%2Fingress-operator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openfaas","download_url":"https://codeload.github.com/openfaas/ingress-operator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247478325,"owners_count":20945266,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["faas","ingress","ingresscontroller","kubernetes","openfaas","operator","serverless"],"created_at":"2024-11-12T15:23:39.498Z","updated_at":"2025-10-03T22:22:39.330Z","avatar_url":"https://github.com/openfaas.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"IngressOperator for OpenFaaS\n====\n\nGet custom domains and TLS for your OpenFaaS Functions through the FunctionIngress CRD\n\n[![build](https://github.com/openfaas/ingress-operator/actions/workflows/build.yaml/badge.svg)](https://github.com/openfaas/ingress-operator/actions/workflows/build.yaml)\n[![OpenFaaS](https://img.shields.io/badge/openfaas-serverless-blue.svg)](https://www.openfaas.com)\n\n## Why is this needed?\n\nOpenFaaS functions are created as pairs with Deployment and Service objects, which eventually go on to create a Pod.\n\nDeployments should not be exposed directly, but accessed via the OpenFaaS Gateway service.\n\nThe gateway in OpenFaaS has a number of roles including:\n* providing HA through N replicas\n* adding tracing IDs\n* adding authz\n* collecting metrics\n* scaling endpoints from zero\n\nUsers started to create `Ingress` records pointing at the gateway for each public endpoint they wanted to host with a specific website address. This Operator automates that.\n\nThis project addresses the following Proposal for Kubernetes: [Proposal: define custom hostname for functions #1082](https://github.com/openfaas/faas/issues/1082)\n\n\u003e Looking for a tutorial? See the [OpenFaaS documentation](https://docs.openfaas.com/reference/authentication/)\n\nMinimum supported cert-manager version: [v1.0](https://cert-manager.io/docs/release-notes/release-notes-1.0/)\n\n## Schema\n\nThis is an Operator / controller to build Kubernetes `Ingress` and `cert-manager` `Certificate` objects for functions.\n\nThe following example would expose the `nodeinfo` function from the store as a URL: `nodeinfo.myfaas.club`.\n\n```yaml\napiVersion: openfaas.com/v1\nkind: FunctionIngress\nmetadata:\n  name: nodeinfo\n  namespace: openfaas\nspec:\n  domain: \"nodeinfo.myfaas.club\"\n  function: \"nodeinfo\"\n  ingressType: \"nginx\"\n  path: \"/v1/profiles/(.*)\" # Optionally set a path for the domain i.e. nodeinfo.myfaas.club/v1/profiles/\n  # tls:\n  #   enabled: true\n  #   issuerRef:\n  #     name: \"letsencrypt-staging\"\n  #     kind: \"Issuer\"\n```\n\nExploring the schema:\n\n* The `domain` field corresponds to a DNS entry which points at your IngressController's public IP, or the IP of one of the hosts if using `HostPort`.\n* `function` refers to the function you want to expose on the domain.\n* `path` set a root path / prefix for the function to be mounted at the domain specified in `domain`\n* `tls` whether to provision a TLS certificate using JetStack's [cert-manager](https://github.com/jetstack/cert-manager)\n* `issuerRef` which issuer to use, this may be a staging or production issuer.\n* `issuerRef.kind` Issuer or ClusterIssuer, This depends on whats available in your cluster\n\n### REST-style mapping of functions\n\nSee an example in the [OpenFaaS docs](https://docs.openfaas.com/reference/ssl/kubernetes-with-cert-manager/#30-rest-style-api-mapping-for-your-functions)\n\n## Status\n\nCompleted backlog items:\n\n- [x] Create `Ingress` records for HTTP\n- [x] Create `Ingress` records for HTTPS\n- [x] Create cert-manager `Certificate` records\n- [x] Support Nginx\n- [x] Support Zoolando's Skipper\n- [x] Support Traefik\n- [x] Support armhf / Raspberry Pi\n- [x] Add `.travis.yml` for CI\n- [x] REST-style path prefixes for functions\n\nRemaining items:\n\n- [ ] Synchronise annotations upon edit of FunctionIngress CRs [#39](https://github.com/openfaas/ingress-operator/issues/)\n\n## Deployment\n\n### Pre-reqs\n\nThere are several pre-reqs for a working installation, but some of these components are installed with OpenFaaS and can also be found in [the docs](https://docs.openfaas.com/).\n\n#### IngressController: `nginx`\n\n[nginx IngressController](https://github.com/helm/charts/tree/master/stable/nginx-ingress) is recommended. Use a HostPort if testing against a local cluster where `LoadBalancer` is unavailable.\n\nMake sure you have [helm](https://github.com/openfaas/faas-netes/blob/master/HELM.md) and Tiller.\n\nInstall [nginx](https://nginx.org/en/docs/) with LoadBalancer:\n\n```sh\nhelm install stable/nginx-ingress --name nginxingress --set rbac.create=true\n```\n\nInstall nginx with host-port:\n\n```sh\nexport ADDITIONAL_SET=\",controller.hostNetwork=true,controller.daemonset.useHostPort=true,dnsPolicy=ClusterFirstWithHostNet,controller.kind=DaemonSet\"\nhelm install stable/nginx-ingress --name nginxingress --set rbac.create=true${ADDITIONAL_SET}\n```\n\n#### OpenFaaS\n\nOpenFaaS is also required:\n\n```\ngit clone https://github.com/openfaas/faas-netes\ncd faas-netes\n\nkubectl apply -f namespaces.yml\n# generate a random password\nPASSWORD=$(head -c 12 /dev/urandom | shasum| cut -d' ' -f1)\n\nkubectl -n openfaas create secret generic basic-auth \\\n--from-literal=basic-auth-user=admin \\\n--from-literal=basic-auth-password=\"$PASSWORD\"\n\necho $PASSWORD \u003e ../password.txt\n\nkubectl apply -f ./yaml\n\nkubectl port-forward -n openfaas deploy/gateway 31112:8080 \u0026\necho -n ${PASSWORD} | faas-cli login --username admin --password-stdin -g 127.0.0.1:31112\nfaas-cli store deploy nodeinfo -g 127.0.0.1:31112\n```\n\n#### Configure DNS records\n\n##### Find your public IP\n\nFind the LB for Nginx:\n\n```\nkubectl get svc -n default\n```\n\nOr find the NodeIP:\n\n```\nkubectl get node -o wide\n```\n\n##### Create DNS A records\n\nYou should now configure your DNS A records:\n\nFor example, `nodeinfo` function in the `myfaas.club` domain and IP `178.128.137.209`:\n\n```\nnodeinfo.myfaas.club  178.128.137.209\n```\n\n\u003e Note: with DigitalOcean's CLI you could run: `doctl compute domain create nodeinfo.myfaas.club --ip-address 178.128.137.209`.\n\n##### TLS: Configure cert-manager\n\nIf using TLS, then install [cert-manager](https://docs.openfaas.com/reference/ssl/kubernetes-with-cert-manager/#install-cert-manager).\n\nNow [create an issuer](https://cert-manager.io/docs/configuration/) to use the staging endpoint:\n\n```yaml\n---\napiVersion: cert-manager.io/v1\nkind: Issuer\nmetadata:\n  name: letsencrypt-staging\n  namespace: openfaas\nspec:\n  acme:\n    # The ACME server URL\n    server: https://acme-staging-v02.api.letsencrypt.org/directory\n    # Email address used for ACME registration\n    email: user@example.com\n    # Name of a secret used to store the ACME account private key\n    privateKeySecretRef:\n      name: letsencrypt-staging\n    # Enable the HTTP-01 challenge provider\n    solvers:\n    # An empty 'selector' means that this solver matches all domains\n    - selector: {}\n      http01:\n        ingress:\n          class: nginx\n```\n\nor ClusterIssuer\n\n```yaml\napiVersion: cert-manager.io/v1\nkind: ClusterIssuer\nmetadata:\n  name: letsencrypt-staging\n  namespace: openfaas\nspec:\n  acme:\n    # The ACME server URL\n    server: https://acme-staging-v02.api.letsencrypt.org/directory\n    # Email address used for ACME registration\n    email: user@example.com\n    # Name of a secret used to store the ACME account private key\n    privateKeySecretRef:\n      name: letsencrypt-staging\n    # Enable the HTTP-01 challenge provider\n    solvers:\n    # An empty 'selector' means that this solver matches all domains\n    - selector: {}\n      http01:\n        ingress:\n          class: nginx\n```\n\n* Edit the `email` and take note of the `namespace`, you will want this to be `openfaas`.\n* If using `traefik` instead of `nginx`, then edit `class: nginx` and replace it as necessary.\n  **Recommended version is v1.7.21 or above**, previous versions will incorrectly route requests\n  to your function (with duplicated path, see\n  [related issue](https://github.com/openfaas/ingress-operator/issues/30)).\n\nSave as `letsencrypt-issuer.yaml` then run `kubectl apply -f letsencrypt-issuer.yaml`.\n\nIf you are confident in the configuration, switch over to the production issuer, but note that it is rate-limited.\n\n* Change `letsencrypt-staging` to `letsencrypt-prod`\n* Edit `https://acme-staging-v02.api.letsencrypt.org/directory` to `https://acme-v02.api.letsencrypt.org/directory`\n\nSave the file and apply.\n\n### Custom annotations\n\nYou can also set custom annotations to be passed down to the Ingress record created by the operator.\n\nExample:\n\nThis example adds one of the required annotations for basic auth as defined in the [ingress-nginx docs](https://kubernetes.github.io/ingress-nginx/examples/auth/basic/).\n\n```yaml\napiVersion: openfaas.com/v1\nkind: FunctionIngress\nmetadata:\n  name: nodeinfo\n  namespace: openfaas\n  annotations:\n    nginx.ingress.kubernetes.io/auth-type: basic\nspec:\n  domain: \"nodeinfo.myfaas.club\"\n  function: \"nodeinfo\"\n  ingressType: \"nginx\"\n```\n\n### Asynchronous functions\n\nThis example exposes the nodeinfo function for asynchronous invocation by rewriting its path to the gateway URL including the `/async-function` prefix instead of the usual `/function/`.\n\n```yaml\napiVersion: openfaas.com/v1\nkind: FunctionIngress\nmetadata:\n  name: nodeinfo\n  namespace: openfaas\n  annotations:\n    nginx.ingress.kubernetes.io/rewrite-target: /async-function/nodeinfo/$1\nspec:\n  domain: \"nodeinfo.myfaas.club\"\n  function: \"nodeinfo\"\n  ingressType: \"nginx\"\n  ```\n\n### Bypass mode\n\nThe IngressOperator can be used to create Ingress records that bypass the OpenFaaS Gateway. This may be useful when you are running a non-standard workload such as a brownfields monolith to reduce hops, or with an unsupported protocol like gRPC or websockets.\n\nExample:\n\n```yaml\napiVersion: openfaas.com/v1\nkind: FunctionIngress\nmetadata:\n  name: nodeinfo\n  namespace: openfaas-fn\nspec:\n  domain: \"nodeinfo.myfaas.club\"\n  function: \"nodeinfo\"\n  ingressType: \"nginx\"\n  bypassGateway: true\n```\n\nNote that since Ingress records must be created in the same namespace as the backend service, `namespace` is changed to `openfaas-fn`.\n\nBy default, the OpenFaaS helm chart can deploy the first instance of the operator, if you need gateway bypass, then deploy a second operator using a customised version of `artifacts/operator-amd64.yaml`.\n\nWhen deploying the operator, you will also need to:\n\n* Set the `ingress_namespace` env-var to `openfaas-fn`\n* Edit the deployment `namespace` to `openfaas-fn`\n* Optionally: edit `artifacts/operator-rbac.yaml` to `openfaas-fn` and apply\n\n### Run or deploy the IngressOperator\n\n#### In-cluster:\n\n```sh\nkubectl apply -R -f ./artifacts/\n\nkubectl logs -n openfaas deploy/ingress-operator\n```\n\n#### Local testing:\n\n```sh\nrm ./artifacts/operator-amd64.yaml\nkubectl apply -R -f ./artifacts/\n\ngo build \u0026\u0026 ./ingress-operator -kubeconfig=./config\n```\n\n## Create your own `FunctionIngress`\n\n### With TLS\n\n```yaml\napiVersion: openfaas.com/v1\nkind: FunctionIngress\nmetadata:\n  name: nodeinfo-tls\n  namespace: openfaas\nspec:\n  domain: \"nodeinfo-tls.myfaas.club\"\n  function: \"nodeinfo\"\n  ingressType: \"nginx\"\n  tls:\n    enabled: true\n    issuerRef:\n      name: \"letsencrypt-staging\"\n      # Change to ClusterIssuer if required\n      # https://cert-manager.io/docs/concepts/issuer/\n      kind: \"Issuer\"\n```\n\n*nodeinfo.yaml*\n\n### Without TLS\n\n```yaml\napiVersion: openfaas.com/v1\nkind: FunctionIngress\nmetadata:\n  name: nodeinfo\n  namespace: openfaas\nspec:\n  domain: \"nodeinfo.myfaas.club\"\n  function: \"nodeinfo\"\n  ingressType: \"nginx\"\n```\n\n*nodeinfo.yaml*\n\n### Apply\n\n```sh\nkubectl apply -f nodeinfo.yaml\n```\n\n### Test:\n\n```\n# Find the ingress record\nkubectl get ingress -n openfaas\n\n# Find the cert record\nkubectl get cert -n openfaas\n\n# Find the FunctionIngress\nkubectl get FunctionIngress -n openfaas\n```\n\nRemember to configure DNS for `nodeinfo.myfaas.club` or edit `/etc/hosts` and point to your `IngressController`'s IP or `LoadBalancer`.\n\n## Kubernetes versions\nIngress Operator currently requires Kubernetes version 1.16+\n\n## Contributing\n\nThis project follows the [OpenFaaS contributing guide](./CONTRIBUTING.md)\n\n## Configuration via Environment Variable\n\n| Option              | Usage                                                                                              |\n|---------------------|----------------------------------------------------------------------------------------------------|\n| `ingress_namespace` | Namespace to create Ingress within, if bypassing gateway, set to `openfaas-fn`. default: `openfaas`|\n\n## LICENSE\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenfaas%2Fingress-operator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenfaas%2Fingress-operator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenfaas%2Fingress-operator/lists"}