{"id":13491573,"url":"https://github.com/cloudtty/cloudtty","last_synced_at":"2026-01-27T11:08:51.712Z","repository":{"id":36965542,"uuid":"486517589","full_name":"cloudtty/cloudtty","owner":"cloudtty","description":"A Friendly Kubernetes CloudShell (Web Terminal) ! ","archived":false,"fork":false,"pushed_at":"2025-11-14T09:54:01.000Z","size":26046,"stargazers_count":628,"open_issues_count":16,"forks_count":79,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-11-14T11:34:08.535Z","etag":null,"topics":["cloudshell","kubernetes","terminal","tty"],"latest_commit_sha":null,"homepage":"https://cloudtty.github.io/cloudtty/","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/cloudtty.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":"MAINTAINERS.md","copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-04-28T08:56:26.000Z","updated_at":"2025-11-14T09:54:08.000Z","dependencies_parsed_at":"2023-02-15T22:15:28.940Z","dependency_job_id":"1a6c9212-62a9-4c6b-baa4-69e2a294d4ef","html_url":"https://github.com/cloudtty/cloudtty","commit_stats":null,"previous_names":[],"tags_count":74,"template":false,"template_full_name":null,"purl":"pkg:github/cloudtty/cloudtty","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtty%2Fcloudtty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtty%2Fcloudtty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtty%2Fcloudtty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtty%2Fcloudtty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudtty","download_url":"https://codeload.github.com/cloudtty/cloudtty/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudtty%2Fcloudtty/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28812371,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T07:41:26.337Z","status":"ssl_error","status_checked_at":"2026-01-27T07:41:08.776Z","response_time":168,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["cloudshell","kubernetes","terminal","tty"],"created_at":"2024-07-31T19:00:58.300Z","updated_at":"2026-01-27T11:08:51.700Z","avatar_url":"https://github.com/cloudtty.png","language":"Go","readme":"# A Kubernetes Cloud Shell (Web Terminal) Operator\n\n[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6301/badge)](https://bestpractices.coreinfrastructure.org/projects/6301)\n\nEnglish | [简体中文](https://github.com/cloudtty/cloudtty/blob/main/README_zh.md)\n\ncloudtty is an easy-to-use operator to run web terminal and cloud shell intended for a kubernetes-native environment.\nYou can easily open a terminal on your own browser via cloudtty.\nThe community is always open for any contributor and those who want to have a try.\n\nLiterally, cloudtty herein refers to a virtual console, shell, or terminal running on web and clouds.\nYou can use it anywhere with an internet connection and it will be automatically connected to the cloud.\n\n\u003e Early user terminals connected to computers were electromechanical teleprinters or teletypewriters (TeleTYpewriter, TTY), which might be the origin of TTY.\n\u003e Gradually, TTY has continued to be used as the name for a text-only console although now this text-only console is a virtual console not a physical console.\n\n\u003cimg src=\"https://github.com/cncf/artwork/blob/main/other/illustrations/ashley-mcnamara/transparent/cncf-cloud-gophers-transparent.png?raw=true\" style=\"width:600px;\" /\u003e\n\n**cloudtty is a [Cloud Native Computing Foundation](https://cncf.io/) landscape project.**\n\n## Why Do You Need cloudtty?\n\nA project [ttyd](https://github.com/tsl0922/ttyd) provides some features to share terminals over the web.\nBut if you use Kubernetes, a more cloud-native enviroment is required to run the webtty via the `kubernetes` way (running as a pod, and generated by CRDs),\nwhich is covered by cloudtty. You are welcome to try cloudtty :tada:.\n\n## Applicable Scenarios\n\n1. Many enterprises use a cloud platform to manage Kubernetes, but due to security reasons,\n   you cannot use SSH to connect the node host to execute `kubectl` commands.\n   In this case, you may require a cloud shell capability.\n\n2. A running container on kubernetes can be \"entered\" (via `Kubectl exec`) on a browser web page.\n\n3. The container logs can be displayed in real time (scrolling) on a browser web page.\n\n## Demo\n\n![screenshot_gif](https://github.com/cloudtty/cloudtty/raw/main/docs/snapshot.gif)\n\nAfter the cloudtty is intergated to your own UI, it would look like:\n\n![demo_png](https://github.com/cloudtty/cloudtty/raw/main/docs/demo.png)\n\n## Quick Start\n\n- Step 1: Install the Operator and CRDs\n\n  a. Install the operator using Helm\n\n  ```shell\n  helm repo add cloudtty https://cloudtty.github.io/cloudtty\n  helm repo update\n  helm install cloudtty-operator --version 0.5.0 cloudtty/cloudtty\n  ```\n\n  b. Wait for the operator pod until it is running\n\n  ```shell\n  kubectl wait deployment cloudtty-operator-controller-manager --for=condition=Available=True\n  ```\n\n- Step 2: Create a cloudtty instance by applying CR, and then monitor its status\n\n  ```shell\n  kubectl apply -f https://raw.githubusercontent.com/cloudtty/cloudtty/v0.5.0/config/samples/local_cluster_v1alpha1_cloudshell.yaml\n  ```\n\n  By default, it will create a cloudtty pod and expose the `NodePort` service.\n  Alternatively, `ClusterIP`, `Ingress`, and `VirtualService`(for Istio) are all supported as `exposureMode`, please refer to `config/samples/` for more examples.\n\n- Step 3: Observe CR status to obtain its web access url, such as:\n\n  ```shell\n  kubectl get cloudshell -w\n  ```\n\n  You can see the following information:\n\n  ```shell\n  NAME                 USER   COMMAND  TYPE        URL                 PHASE   AGE\n  cloudshell-sample    root   bash     NodePort    192.168.4.1:30167   Ready   31s\n  cloudshell-sample2   root   bash     NodePort    192.168.4.1:30385   Ready   9s\n  ```\n\n  When the status of cloudshell changes to `Ready` and the `URL` field appears, copy and paste the URL on your browser to access the cluster with `kubectl`, as shown below:\n\n  ![screenshot_png](https://github.com/cloudtty/cloudtty/raw/main/docs/snapshot.png)\n\n### How to build customize cloudshell image\n\nMost users need more than just the basic `kubectl` tools to manage their clusters. we can customize image based on cloudshell base image. here is an example of adding the `karmadactl` tool.\n\n- Modify [Dockerfile.example](https://github.com/cloudtty/cloudtty/blob/main/docker/Dockerfile.example).\n\n  ```shell\n  FROM ghcr.io/cloudtty/cloudshell:v0.6.0\n\n  RUN curl -fsSLO https://github.com/karmada-io/karmada/releases/download/v1.2.0/kubectl-karmada-linux-amd64.tgz \\\n      \u0026\u0026 tar -zxf kubectl-karmada-linux-amd64.tgz \\\n      \u0026\u0026 chmod +x kubectl-karmada \\\n      \u0026\u0026 mv kubectl-karmada /usr/local/bin/kubectl-karmada \\\n      \u0026\u0026 which kubectl-karmada\n\n  ENTRYPOINT ttyd\n  ```\n\n- Rebuild new image with `karmadactl` tool：\n\n  ```shell\n  docker build -t \u003cIMAGE\u003e . -f docker/Dockerfile-webtty\n  ```\n\n### Use customize cloudshell image\n\nThere are two ways to set the customized cloudshell image:\n\n1. You can set the image directly by using the cloudshell CR field `spec.image`.\n\n    ```yaml\n    apiVersion: cloudshell.cloudtty.io/v1alpha1\n    kind: CloudShell\n    metadata:\n      name: cloudshell-sample\n    spec:\n      secretRef: \n        name: \"my-kubeconfig\"\n      image: ghcr.io/cloudtty/customize_cloudshell:latest\n    ```\n\n2. Set the 'JobTemplate' image parameter to run the customized cloudshell image when installing cloudtty.\n\n    ```shell\n    helm install cloudtty-operator --version 0.5.0 cloudtty/cloudtty --set jobTemplate.image.registry=\u003c/REGISTRY\u003e --set jobTemplate.image.repository=\u003c/REPOSITORY\u003e --set jobTemplate.image.tag=\u003c/TAG\u003e\n    ```\n\n\u003e If you have installed cloudtty, you can also modify the configMap of JobTemplate to set the cloudshell image.\n\n## Advanced Usage Guide\n\n### Manage Multiple or Remote Clusters\n\nIf cloudtty manages a remote cluster (another cluster than which the cloudtty operator runs on),\nyou need tell cloudtty the kube.conf of the remote cluster as below.\n\nYou can copy the kube.config, `~/.kube/config`, from a remote cluster.\n\n```shell\nkubectl create secret generic my-kubeconfig --from-file=kube.config\n```\n\nBe careful to ensure the `/root/.kube/config`:\n\n1. contains the base64 encoded certs/secrets instead of local files.\n\n2. can reach the k8s api-server endpoint (via host IP or cluster IP) instead of localhost.\n\n- If the cluster is remote, `cloudtty` needs to specify `kubeconfig` to access the cluster using the kubectl command tool.\n  You need to provide the kubeconfig stored in secret and specify the name to cloudshell `spec.secretRef.name` CR.\n  kubeconfig will be automatically mounted to the cloudtty container.\n  Ensure that the server IP address is properly connected to the cluster network.\n\n- If cloudtty runs on the same cluster which to be managed,\n  you don't need to do this (a ServiceAccount with `cluster-admin` role permissions will be binded to the pod automaticlly.\n  Inside the container, kubectl automatically detects `CA` certificates and token.\n  If any concern with security, you can also provide your own kubeconfig to control the permissions for different users.)\n\n### Manager cluster node\n\nThe basic image to cloudshell had integrated with the plugin of [kubectl-node-shell](https://github.com/kvaps/kubectl-node-shell), you can use its command to connect an arbitrary node of specified cluster. It will run a pod with privilege, if you attach importance to the pod security, please be careful with the feature. See the following sample:\n\n```yaml\napiVersion: cloudshell.cloudtty.io/v1alpha1\nkind: CloudShell\nmetadata:\n  name: cloudshell-node-shell\nspec:\n  secretRef:\n    name: \"\u003cKUBECONFIG\u003e\"\n  commandAction: \"kubectl node-shell \u003cNODE_NAME\u003e\"\n```\n\nFor more samples refer to [kubectl-node-shell](https://github.com/kvaps/kubectl-node-shell).\n\n\u003e If a cluster has the security policy such as `PodSecurity` and `PSP`, the feature may be affected.\n\n### More Exposure Modes\n\nCloudtty provides the following four modes to expose cloudtty services to satisfy different usage scenarios:\n\n- `ClusterIP`: [Service](https://kubernetes.io/docs/concepts/services-networking/service/) ClusterIP type in a cluster,\n  which is suitable for third-party integration of cloudtty server. You can choose a more flexible way to expose your services.\n\n- `NodePort` (default): The simplest way to expose the service mode is to create a service resource with type NodePort in a cluster.\n  You can access the cloudtty service using the master node IP address and port number.\n\n- `Ingress`: Create a Service resource of ClusterIP type in a cluster and create an ingress resource to load the service based on routing rules.\n  This works when the [Ingress Controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) is used for traffic load in the cluster.\n\n- `VirtualService` (Istio): Create a ClusterIP Service resource in a cluster and create a `VirtaulService` resource.\n  This mode is used when [Istio](https://github.com/istio/istio) is used to load traffic in a cluster.\n\n### featureGate\n\n`AllowSecretStoreKubeconfig`：Restore kubeconfig file with secret resource, if the featureGate is enabled, the field `spec.configmapName` will be disabled.\nYou can use the field `spec.secretRef.name` to difine where kubeconfig is. Currently the featureGate is in alpha phase, disabled by default.\n\n#### How to open featrueGate\n\n1. If you use `yaml` to deploy cloudtty, add `--feature-gates=AllowSecretStoreKubeconfig=true` to operator to run arguments.\n2. If you use `helm` to deploy cloudtty, set the parameter `--set image.featureGates.AllowSecretStoreKubeconfig=true`.\n\n## Rationale\n\n1. Operator creates a job and a service with the same name in the proper namespace.\n   If `Ingress` or `VirtualService` is used, it also creates the routing information.\n\n2. When the pod status is `Ready`, it will show the access url to the cloudshell status.\n\n3. When a [job](https://kubernetes.io/docs/concepts/workloads/controllers/job/) ends after the TTL is expired or the job is terminated for some other reasons,\n   the cloudshell status changes to `Completed` once the job changes to `Completed`.\n   You can set cloudshell to delete associated resources when the status is `Completed`.\n\n4. When cloudshell is deleted, the corresponding job and service (through 'ownerReference') are automatically deleted.\n   If Ingress or VirtualService mode is used, the corresponding routing information will be deleted too.\n\n## Developer Guide\n\n### Run the Operator and Install CRDs\n\n1. Generate CRDs to [charts/_crds](charts/cloudtty/_crds/)\n\n    ```shell\n    make generate-yaml\n    ```\n\n2. Install CRDs\n\n    ```shell\n    make install\n    ```\n\n3. Run the operator\n\n    ```shell\n    make run\n    ```\n\n### Create cloudshell\n\nFor example, automatically print logs for a container.\n\n```yaml\napiVersion: cloudshell.cloudtty.io/v1alpha1\nkind: CloudShell\nmetadata:\n  name: cloudshell-sample\nspec:\n  secretRef:\n    name: \"my-kubeconfig\"\n  runAsUser: \"root\"\n  commandAction: \"kubectl -n kube-system logs -f kube-apiserver-cn-stack\"\n  once: false\n```\n\n## Special Thanks\n\nThis project is based on https://github.com/tsl0922/ttyd. Many thanks to `tsl0922`, `yudai`, and the community.\nThe frontend UI code was originated from `ttyd` project, and the ttyd binary inside the container also comes from `ttyd` project.\n\n## Discussion\n\nIf you have any question, feel free to reach out to us in the following ways:\n\n- [Slack Channel](https://cloud-native.slack.com/archives/C03LA6AUF7V)\n\n- WeChat Group: contact `calvin0327`(wen.chen@daocloud.io) to join\n\n## What's Next\n\n- Control permissions through RBAC (to generate the `/var/run/secret` file).\n\n- For security, jobs should run in separate namespaces, not in the namespace same as  cloudshell.\n\n- Check the pod is running and endpoint status changes to `Ready`, and the cloudshell phase is set to `Ready`.\n\n- TTL should be set to both job and shell.\n\n- Job creation templates are currently hardcode and should provide a more flexible way to modify the job template.\n\nMore will be coming Soon. Welcome to [open an issue](https://github.com/cloudtty/cloudtty/issues) and [propose a PR](https://github.com/cloudtty/cloudtty/pulls). 🎉🎉🎉\n\n## Contributors\n\n\u003ca href=\"https://github.com/cloudtty/cloudtty/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=cloudtty/cloudtty\" /\u003e\n\u003c/a\u003e\n\nMade with [contrib.rocks](https://contrib.rocks).\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://landscape.cncf.io/images/left-logo.svg\" width=\"300\"/\u003e\u0026nbsp;\u0026nbsp;\u003cimg src=\"https://landscape.cncf.io/images/right-logo.svg\" width=\"350\"/\u003e\n\u003cbr/\u003e\u003cbr/\u003e\ncloudtty enriches the \u003ca href=\"https://landscape.cncf.io/?selected=cloud-tty\"\u003eCNCF CLOUD NATIVE Landscape.\u003c/a\u003e\n\u003c/p\u003e\n","funding_links":[],"categories":["Go","Developer Workspaces \u0026 Productivity"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudtty%2Fcloudtty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudtty%2Fcloudtty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudtty%2Fcloudtty/lists"}