{"id":32652512,"url":"https://github.com/drengskapur/ghostwire","last_synced_at":"2025-10-31T08:06:57.900Z","repository":{"id":319399136,"uuid":"1076882367","full_name":"drengskapur/ghostwire","owner":"drengskapur","description":"Cloud-native Signal Desktop for Kubernetes - Browser-based access with infrastructure-level security","archived":false,"fork":false,"pushed_at":"2025-10-26T17:46:52.000Z","size":2607,"stargazers_count":4,"open_issues_count":2,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-26T19:31:31.201Z","etag":null,"topics":["browser-access","cert-manager","cloud-native","electron","gitops","helm","kasmvnc","kubernetes","oauth2","persistent-storage","remote-desktop","signal","signal-desktop","statefulset","vnc"],"latest_commit_sha":null,"homepage":"https://github.com/drengskapur/ghostwire","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drengskapur.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-15T13:27:06.000Z","updated_at":"2025-10-26T17:45:58.000Z","dependencies_parsed_at":"2025-10-26T19:19:21.737Z","dependency_job_id":null,"html_url":"https://github.com/drengskapur/ghostwire","commit_stats":null,"previous_names":["drengskapur/ghostwire"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/drengskapur/ghostwire","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drengskapur%2Fghostwire","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drengskapur%2Fghostwire/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drengskapur%2Fghostwire/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drengskapur%2Fghostwire/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drengskapur","download_url":"https://codeload.github.com/drengskapur/ghostwire/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drengskapur%2Fghostwire/sbom","scorecard":{"id":1239235,"data":{"date":"2025-10-26T17:46:18Z","repo":{"name":"github.com/drengskapur/ghostwire","commit":"0fcdaafdcb2e8797fe9abd9c3ddee745f89f4d68"},"scorecard":{"version":"v5.3.0","commit":"c22063e786c11f9dd714d777a687ff7c4599b600"},"score":6.4,"checks":[{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1","Info: detected update tool: RenovateBot: renovate.json:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dependency-update-tool"}},{"name":"Maintained","score":0,"reason":"project was created within the last 90 days. Please review its contents carefully","details":["Warn: Repository was created within the last 90 days."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#maintained"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#security-policy"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/bot-pr-automation.yml:15","Info: jobLevel 'contents' permission set to 'read': .github/workflows/build-tools-image.yml:42","Info: jobLevel 'contents' permission set to 'read': .github/workflows/build-tools-image.yml:83","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:23","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:45","Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:71","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:72","Info: jobLevel 'packages' permission set to 'read': .github/workflows/codeql.yml:69","Info: jobLevel 'contents' permission set to 'read': .github/workflows/devcontainer.yml:45","Info: jobLevel 'contents' permission set to 'read': .github/workflows/devcontainer.yml:88","Info: jobLevel 'contents' permission set to 'read': .github/workflows/fuzzing.yml:16","Info: jobLevel 'contents' permission set to 'read': .github/workflows/fuzzing.yml:41","Info: jobLevel 'contents' permission set to 'read': .github/workflows/helm-release.yml:32","Warn: jobLevel 'packages' permission set to 'write': .github/workflows/helm-release.yml:65","Info: jobLevel 'contents' permission set to 'read': .github/workflows/helm-release.yml:127","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/helm-release.yml:181","Warn: jobLevel 'packages' permission set to 'write': .github/workflows/helm-release.yml:182","Info: jobLevel 'contents' permission set to 'read': .github/workflows/security-scan.yml:71","Info: found token with 'none' permissions: .github/workflows/security-scan.yml:1","Info: jobLevel 'contents' permission set to 'read': .github/workflows/security-scan.yml:23","Info: jobLevel 'contents' permission set to 'read': .github/workflows/security-scan.yml:45","Info: jobLevel 'contents' permission set to 'read': .github/workflows/validate-config.yml:20","Info: found token with 'none' permissions: .github/workflows/bot-pr-automation.yml:1","Info: found token with 'none' permissions: .github/workflows/build-tools-image.yml:1","Info: found token with 'none' permissions: .github/workflows/codeql.yml:1","Info: found token with 'none' permissions: .github/workflows/devcontainer.yml:1","Info: found token with 'none' permissions: .github/workflows/fuzzing.yml:1","Info: found token with 'none' permissions: .github/workflows/helm-release.yml:1","Info: topLevel 'contents' permission set to 'read': .github/workflows/k3d-test.yml:28","Info: topLevel permissions set to 'read-all': .github/workflows/scorecard.yml:20","Info: found token with 'none' permissions: .github/workflows/security-scan.yml:1","Info: found token with 'none' permissions: .github/workflows/validate-config.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#token-permissions"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#vulnerabilities"}},{"name":"CII-Best-Practices","score":2,"reason":"badge detected: InProgress","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#cii-best-practices"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v1.3.1 not signed: https://api.github.com/repos/drengskapur/ghostwire/releases/255728402","Warn: release artifact v1.3.0 not signed: https://api.github.com/repos/drengskapur/ghostwire/releases/255726880","Warn: release artifact v1.2.3 not signed: https://api.github.com/repos/drengskapur/ghostwire/releases/255488472","Warn: release artifact v1.2.2 not signed: https://api.github.com/repos/drengskapur/ghostwire/releases/255488322","Warn: release artifact v1.2.1 not signed: https://api.github.com/repos/drengskapur/ghostwire/releases/255488073","Warn: release artifact v1.3.1 does not have provenance: https://api.github.com/repos/drengskapur/ghostwire/releases/255728402","Warn: release artifact v1.3.0 does not have provenance: https://api.github.com/repos/drengskapur/ghostwire/releases/255726880","Warn: release artifact v1.2.3 does not have provenance: https://api.github.com/repos/drengskapur/ghostwire/releases/255488472","Warn: release artifact v1.2.2 does not have provenance: https://api.github.com/repos/drengskapur/ghostwire/releases/255488322","Warn: release artifact v1.2.1 does not have provenance: https://api.github.com/repos/drengskapur/ghostwire/releases/255488073"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":9,"reason":"dependency not pinned by hash detected -- score normalized to 9","details":["Warn: containerImage not pinned by hash: .devcontainer/Dockerfile:2: pin your Docker image by updating mcr.microsoft.com/devcontainers/go:1.23-bookworm to mcr.microsoft.com/devcontainers/go:1.23-bookworm@sha256:35e445a87924ae04c171d7e52e2a913050dfefbacda3756ef7a307db035704d5","Warn: downloadThenRun not pinned by hash: .devcontainer/Dockerfile:6-7","Warn: npmCommand not pinned by hash: .devcontainer/Dockerfile:37-38","Warn: npmCommand not pinned by hash: scripts/test-k3d-playwright.sh:136","Info:  27 out of  27 GitHub-owned GitHubAction dependencies pinned","Info:  55 out of  55 third-party GitHubAction dependencies pinned","Info:   1 out of   2 containerImage dependencies pinned","Info:   0 out of   1 downloadThenRun dependencies pinned","Info:   0 out of   2 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/build-tools-image.yml:28"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#packaging"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (8) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#sast"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'main'","Warn: branch 'main' does not require approvers","Warn: codeowners review is not required on branch 'main'","Info: status check found to merge onto on branch 'main'","Warn: PRs are not required to make changes on branch 'main'; or we don't have data to detect it.If you think it might be the latter, make sure to run Scorecard with a PAT or use Repo Rules (that are always public) instead of Branch Protection settings"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#branch-protection"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#fuzzing"}},{"name":"CI-Tests","score":10,"reason":"8 out of 8 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#ci-tests"}},{"name":"Contributors","score":0,"reason":"project has 0 contributing companies or organizations -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/c22063e786c11f9dd714d777a687ff7c4599b600/docs/checks.md#contributors"}}]},"last_synced_at":"2025-10-26T19:32:25.501Z","repository_id":319399136,"created_at":"2025-10-26T19:32:25.508Z","updated_at":"2025-10-26T19:32:25.508Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281953450,"owners_count":26589146,"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","status":"online","status_checked_at":"2025-10-31T02:00:07.401Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["browser-access","cert-manager","cloud-native","electron","gitops","helm","kasmvnc","kubernetes","oauth2","persistent-storage","remote-desktop","signal","signal-desktop","statefulset","vnc"],"created_at":"2025-10-31T08:03:42.905Z","updated_at":"2025-10-31T08:06:57.893Z","avatar_url":"https://github.com/drengskapur.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n![Ghostwire Logo](brand/logo/ghostwire-logo-horizontal.png)\n\n## Cloud-Native Signal Desktop for Kubernetes\n\nRun Signal Desktop in your cluster with browser access and persistent storage\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n[![Release](https://img.shields.io/github/v/release/drengskapur/ghostwire)](https://github.com/drengskapur/ghostwire/releases)\n[![Lint and Test](https://github.com/drengskapur/ghostwire/actions/workflows/helm-release.yml/badge.svg?branch=main)](https://github.com/drengskapur/ghostwire/actions/workflows/helm-release.yml)\n[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/ghostwire)](https://artifacthub.io/packages/search?repo=ghostwire)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/drengskapur/ghostwire/badge)](https://scorecard.dev/viewer/?uri=github.com/drengskapur/ghostwire)\n\n\u003c/div\u003e\n\n---\n\n## What This Does\n\nDeploys Signal Desktop in Kubernetes with:\n\n- Browser-based VNC access (no client needed)\n- Persistent storage (conversations survive pod restarts)\n- Integration with your existing infrastructure (OAuth2, ingress, cert-manager)\n\n\u003cdiv align=\"center\"\u003e\n\n![Signal Desktop in Kubernetes](docs/images/signal-desktop-linking.png)\n\n\u003c/div\u003e\n\n---\n\n## Quick Start\n\nInstall the chart:\n\n```bash\nhelm install ghostwire oci://ghcr.io/drengskapur/charts/ghostwire --version 0.0.0-latest --create-namespace -n ghostwire\n```\n\nAccess via port-forward:\n\n```bash\nkubectl port-forward -n ghostwire svc/ghostwire 6901:6901\n```\n\nOpen in browser:\n\n```text\nhttp://localhost:6901?keyboard=1\n```\n\n**Note:** VNC authentication is disabled by default. For production use, configure ingress with OAuth2 instead of port-forwarding. See [Chart README](chart/README.md).\n\n---\n\n## Why This Exists\n\nMost VNC-in-Kubernetes solutions bundle their own authentication, TLS termination, and security controls. This creates redundant configuration and conflicts with platform-level security tools.\n\nGhostwire takes a different approach: **delegate infrastructure concerns to infrastructure**.\n\n**What we don't include:**\n\n- Built-in authentication (use OAuth2-proxy or similar)\n- Built-in TLS (use cert-manager)\n- Custom ingress configuration (use your existing ingress controller)\n\n**What we do well:**\n\n- Run Signal Desktop reliably in a container\n- Persist your data correctly (StatefulSet + PVC)\n- Expose VNC via standard Service\n- Stay out of your infrastructure's way\n\nThis means less configuration overlap and easier integration with tools you already use.\n\n---\n\n## Architecture\n\n```mermaid\narchitecture-beta\n    group internet(cloud)[Internet]\n    group cloud(cloud)[Cloud Provider]\n    group k8s(cloud)[Kubernetes Cluster] in cloud\n    group ns_infra(cloud)[Ingress Namespace] in k8s\n    group ns_app(cloud)[App Namespace] in k8s\n\n    service user(internet)[User] in internet\n    service lb(internet)[Load Balancer] in cloud\n    service ingress(server)[NGINX Ingress] in ns_infra\n    service oauth(server)[OAuth2 Proxy] in ns_infra\n    service svc(server)[Service] in ns_app\n    service pod(server)[Pod] in ns_app\n    service pv(disk)[PV] in cloud\n    service pvc(disk)[PVC] in ns_app\n\n    user:R -- L:lb\n    lb:R -- L:ingress\n    ingress:R -- L:oauth\n    oauth:R -- L:svc\n    svc:R -- L:pod\n    pod:B -- T:pvc\n    pvc:B -- T:pv\n```\n\nClean separation: the chart handles the application runtime, your platform handles everything else.\n\n---\n\n## Configuration\n\nThe chart exposes 60+ Helm values. Key parameters:\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| `persistence.size` | `10Gi` | Signal data volume size |\n| `resources.limits.memory` | `4Gi` | Memory limit |\n| `resources.requests.cpu` | `500m` | CPU request |\n| `image.tag` | `1.18.0-rolling-daily` | Signal Desktop version |\n\nSee [values.yaml](chart/values.yaml) for complete options and [values.schema.json](chart/values.schema.json) for validation.\n\n---\n\n## Documentation\n\n- **[Chart README](chart/README.md)** - Installation guide and configuration reference\n- **[Container Architecture](docs/container-architecture.md)** - How the runtime works\n- **[Deployment Strategies](docs/deployment-strategies.md)** - StatefulSet design and rollout behavior\n- **[Infrastructure Integration](docs/infrastructure-integration-guide.md)** - Patterns for OAuth2, ingress, cert-manager\n- **[Testing Strategy](docs/testing-strategy.md)** - Testing approach and quality assurance\n- **[Fuzzing Strategy](docs/fuzzing-strategy.md)** - Property-based testing and fuzzing approach\n- **[OpenSSF Best Practices Guide](docs/openssf-best-practices.md)** - Security badge application guide\n- **[Code Review Strategy](docs/code-review-strategy.md)** - Single-maintainer approach and co-maintainer call\n\n---\n\n## Contributing\n\n**Looking for Co-Maintainers!** This project is actively seeking additional maintainers to help with code review, issue triage, and feature development. If you're interested, please see [Code Review Strategy](docs/code-review-strategy.md) and reach out via [GitHub Discussions](https://github.com/drengskapur/ghostwire/discussions).\n\nContributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for:\n\n- Development environment setup\n- Testing requirements\n- Commit message conventions\n- Pull request guidelines\n\n---\n\n## License\n\n- **This Helm chart:** Apache License 2.0 ([LICENSE](LICENSE))\n- **Signal Desktop:** AGPLv3 ([Signal Messenger LLC](https://signal.org))\n- **Kasm container images:** MIT License ([Kasm Technologies Inc](https://kasmweb.com))\n\nSee [NOTICE](NOTICE) for third-party software attributions.\n\n**Important:** Signal Messenger LLC and Kasm Technologies Inc do not endorse or support this project.\n\n---\n\n## Built With\n\n- [Signal Desktop](https://github.com/signalapp/Signal-Desktop) - Encrypted messaging application\n- [Kasm Workspaces](https://github.com/kasmtech/workspaces-images) - Containerized desktop streaming\n- [KasmVNC](https://github.com/kasmtech/KasmVNC) - VNC server with HTML5 client\n- [XFCE](https://xfce.org/) - Lightweight desktop environment\n\n---\n\n## Support\n\n- **Documentation:** [chart/README.md](chart/README.md)\n- **Bug Reports:** [GitHub Issues](https://github.com/drengskapur/ghostwire/issues)\n- **Questions:** [GitHub Discussions](https://github.com/drengskapur/ghostwire/discussions)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrengskapur%2Fghostwire","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrengskapur%2Fghostwire","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrengskapur%2Fghostwire/lists"}