{"id":50263463,"url":"https://github.com/andreistefanciprian/urlshortener-gitops","last_synced_at":"2026-05-27T12:06:40.125Z","repository":{"id":338419387,"uuid":"1157807778","full_name":"andreistefanciprian/urlshortener-gitops","owner":"andreistefanciprian","description":"GitOps repo for deploying the urlshortener app and its infrastructure dependencies ","archived":false,"fork":false,"pushed_at":"2026-04-18T05:43:37.000Z","size":114,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-18T06:29:43.103Z","etag":null,"topics":["cloudflare","gitops","kubernetes","urlshortener"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andreistefanciprian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"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":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-14T10:28:23.000Z","updated_at":"2026-03-15T07:15:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/andreistefanciprian/urlshortener-gitops","commit_stats":null,"previous_names":["andreistefanciprian/urlshortener-gitops"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/andreistefanciprian/urlshortener-gitops","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreistefanciprian%2Furlshortener-gitops","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreistefanciprian%2Furlshortener-gitops/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreistefanciprian%2Furlshortener-gitops/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreistefanciprian%2Furlshortener-gitops/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andreistefanciprian","download_url":"https://codeload.github.com/andreistefanciprian/urlshortener-gitops/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreistefanciprian%2Furlshortener-gitops/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33565035,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"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":["cloudflare","gitops","kubernetes","urlshortener"],"created_at":"2026-05-27T12:06:39.204Z","updated_at":"2026-05-27T12:06:40.119Z","avatar_url":"https://github.com/andreistefanciprian.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitOps Kubernetes Deployments with FluxCD\n\nThis repository contains Kubernetes manifests managed by [FluxCD](https://fluxcd.io/) for automated GitOps deployments of the [URL Shortener](https://github.com/andreistefanciprian/urlshortener) application to a [private GKE cluster](https://github.com/andreistefanciprian/urlshortener/tree/main/terraform).\n\n## Deployed Components\n\n### Infrastructure\n\n|  | Tool | Description |\n|------|------|-------------|\n| \u003cimg src=\"https://raw.githubusercontent.com/cncf/artwork/main/projects/flux/icon/color/flux-icon-color.png\" height=\"30\"\u003e | [FluxCD](https://fluxcd.io/flux/) | GitOps toolkit for Kubernetes |\n| \u003cimg src=\"https://raw.githubusercontent.com/cncf/artwork/main/projects/prometheus/icon/color/prometheus-icon-color.png\" height=\"30\"\u003e | [Kube-Prometheus-Stack](https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack) | Monitoring and alerting |\n| \u003cimg src=\"https://raw.githubusercontent.com/cert-manager/cert-manager/master/logo/logo.png\" height=\"30\"\u003e | [Cert-Manager](https://cert-manager.io/docs/installation/helm/) | Automatic TLS certificate management |\n| \u003cimg src=\"https://raw.githubusercontent.com/cncf/artwork/main/projects/kubernetes/icon/color/kubernetes-icon-color.png\" height=\"30\"\u003e | [Gateway API](https://gateway-api.sigs.k8s.io/) | Kubernetes Gateway API CRDs |\n| \u003cimg src=\"https://raw.githubusercontent.com/cncf/artwork/main/projects/kubernetes/icon/color/kubernetes-icon-color.png\" height=\"30\"\u003e | [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/introduction) | Secret management integration |\n| \u003cimg src=\"https://raw.githubusercontent.com/external-secrets/external-secrets/main/assets/eso-logo-medium.png\" height=\"30\"\u003e | [External Secrets Operator](https://external-secrets.io/) | Syncs secrets from GCP Secret Manager into Kubernetes |\n| \u003cimg src=\"https://raw.githubusercontent.com/cncf/artwork/main/projects/kubernetes/icon/color/kubernetes-icon-color.png\" height=\"30\"\u003e | [External DNS](https://kubernetes-sigs.github.io/external-dns/) | Automatic DNS record management (Cloudflare + Route53) |\n| \u003cimg src=\"https://raw.githubusercontent.com/traefik/traefik/master/docs/content/assets/img/traefik.logo.png\" height=\"30\"\u003e | [Traefik](https://doc.traefik.io/traefik/) | Ingress and Gateway API controller with GKE internal load balancer |\n| \u003cimg src=\"https://raw.githubusercontent.com/cncf/artwork/main/projects/kubernetes/icon/color/kubernetes-icon-color.png\" height=\"30\"\u003e | [Priority Classes](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/) | Pod scheduling priority configuration |\n\n### URL Shortener Application\n\n|  | Tool | Description |\n|------|------|-------------|\n| \u003cimg src=\"https://cdn.simpleicons.org/postgresql\" height=\"30\"\u003e | [PostgreSQL](https://github.com/bitnami/charts/tree/main/bitnami/postgresql) | Relational database (`urls` DB, `short_links` table, credentials from GCP Secret Manager) |\n| \u003cimg src=\"https://cdn.simpleicons.org/redis\" height=\"30\"\u003e | [Redis](https://github.com/bitnami/charts/tree/main/bitnami/redis) | In-memory cache (standalone, credentials from GCP Secret Manager) |\n| \u003cimg src=\"https://raw.githubusercontent.com/andreistefanciprian/urlshortener/main/urlshortener_logo.png\" height=\"30\"\u003e | [url-gen](https://github.com/andreistefanciprian/urlshortener/tree/main/url-gen) | gRPC backend service for URL generation |\n| \u003cimg src=\"https://raw.githubusercontent.com/andreistefanciprian/urlshortener/main/urlshortener_logo.png\" height=\"30\"\u003e | [url-read](https://github.com/andreistefanciprian/urlshortener/tree/main/url-read) | gRPC backend service for URL reading |\n| \u003cimg src=\"https://raw.githubusercontent.com/andreistefanciprian/urlshortener/main/urlshortener_logo.png\" height=\"30\"\u003e | [api-gateway](https://github.com/andreistefanciprian/urlshortener/tree/main/api-gateway) | gRPC gateway aggregating url-gen and url-read backends |\n| \u003cimg src=\"https://raw.githubusercontent.com/andreistefanciprian/urlshortener/main/urlshortener_logo.png\" height=\"30\"\u003e | [frontend](https://github.com/andreistefanciprian/urlshortener/tree/main/frontend) | Web frontend communicating with api-gateway |\n\n## Initial Setup\n\n### Prerequisites\n\n- GitHub App for Flux authentication ([setup guide](https://fluxcd.io/blog/2025/04/flux-operator-github-app-bootstrap/#github-app-docs))\n- GKE cluster provisioned via [terraform](https://github.com/andreistefanciprian/terraform-kubernetes-gke-cluster)\n- `kubectl` configured to access your cluster\n- `helmfile` installed locally\n\n### Installation Steps\n\n#### 1. Create GitHub App Secret\n\nFollow the [Flux Operator GitHub App docs](https://fluxcd.io/blog/2025/04/flux-operator-github-app-bootstrap/#github-app-docs) to create a GitHub App, then create the Kubernetes secret:\n\n```bash\nkubectl create namespace flux-system\nflux create secret githubapp flux-system \\\n  --app-id=\u003capp_id\u003e \\\n  --app-installation-id=\u003capp_install_id\u003e \\\n  --app-private-key=\u003cprivate_key.pem\u003e\n```\n\n#### 2. Update Configuration\n\nUpdate the `GCP_PROJECT` variable in:\n- `clusters/home/flux-system/cluster-vars.yaml`\n- `clusters/home/flux-system/values-flux-instance.yaml`\n\n\u003e **Note:** Variables in the ConfigMap are propagated across all manifests in the `./infra` folder.\n\n#### 3. Upload Secrets to GCP Secret Manager\n\nThe following secrets are **not stored in Git**. They are created automatically by [External Secrets Operator](https://external-secrets.io/), which pulls values from GCP Secret Manager:\n\n| Secret | Namespace | GCP Secret Manager key(s) |\n|--------|-----------|---------------------------|\n| `cloudflare-api-token` | `external-dns`, `cert-manager` | `${CLUSTER_NAME}-cloudflare-api-token` |\n| `redis-password` | `redis` | `${CLUSTER_NAME}-redis-password` |\n| `pg-creds` | `postgres` | `${CLUSTER_NAME}-db-admin-password`, `${CLUSTER_NAME}-db-user-password`, `${CLUSTER_NAME}-db-replication-password` |\n| `pg-creds` | `url-gen` | `${CLUSTER_NAME}-db-user-password` |\n| `redis-creds` | `url-gen` | `${CLUSTER_NAME}-redis-password` |\n| `pg-creds` | `url-read` | `${CLUSTER_NAME}-db-user-password` |\n| `redis-creds` | `url-read` | `${CLUSTER_NAME}-redis-password` |\n\nYou must manually create and upload all secrets to GCP Secret Manager before deploying:\n\n```bash\nPROJECT_NAME=\"home\"\n\n# Create and populate random passwords for Redis and PostgreSQL\nfor secret in redis-password db-admin-password db-user-password db-replication-password; do\n  echo -n \"$(openssl rand -base64 32)\" | gcloud secrets versions add ${PROJECT_NAME}-${secret} --data-file=-\ndone\n\n# Create Cloudflare API token secret with DNS Edit permission\necho -n \"\u003cyour-cloudflare-api-token\u003e\" | gcloud secrets versions add ${PROJECT_NAME}-cloudflare-api-token --data-file=-\n```\n\n\u003e **Note:** The secrets must already exist in GCP Secret Manager before running `gcloud secrets versions add`.\n\n#### 4. Deploy Flux Operator and Instance\n\n```bash\n# Authenticate to GHCR to be able to pull flux operator images\nhelm registry login ghcr.io --username \u003cyour-github-username\u003e --password \u003cgithub-PAT\u003e\n\n# Preview changes\nhelmfile -f clusters/home/flux-system/helmfile.yaml diff -l name=flux-operator\n\n# Deploy operator\nhelmfile -f clusters/home/flux-system/helmfile.yaml apply -l name=flux-operator\n\n# Deploy instance\n# Preview changes\nhelmfile -f clusters/home/flux-system/helmfile.yaml diff -l name=flux-instance\n\n# Deploy instance\nhelmfile -f clusters/home/flux-system/helmfile.yaml apply -l name=flux-instance\n```\n\n#### 5. Access Flux Operator UI\n\nThe Flux Operator UI is exposed via a private Cloudflare Tunnel ingress and is accessible at:\n\n**https://flux-operator.9tzy.xyz/**\n\n\u003e **Note:** This is a private ingress. You must have [Cloudflare WARP](https://developers.cloudflare.com/cloudflare-one/connections/connect-devices/warp/) installed and connected to access it. See the [Cloudflare infrastructure setup](https://github.com/andreistefanciprian/urlshortener/tree/main/terraform) for details.\n\nAlternatively, you can access it locally via port-forward:\n\n```bash\nkubectl port-forward svc/flux-operator -n flux-system 9080:9080\n# Open in browser: http://localhost:9080\n```\n\n\n## Monitoring \u0026 Debugging\n\n```bash\n# View all Flux resources\nkubectl get kustomizations -A\nkubectl get helmrepositories -A\nkubectl get helmreleases -A\nkubectl get gitrepositories -A\nkubectl get imagerepositories -A\nkubectl get imageupdateautomations -A\n\n# Check Helm releases\nhelm list -A\nhelm get manifest \u003crelease-name\u003e\n\n# Force reconciliation of a specific app\nflux reconcile kustomization \u003capp-name\u003e --with-source\n\n# Flux controller logs\nkubectl -n flux-system logs -l app=helm-controller -f\n\n# Delete application\nkubectl delete kustomization \u003capp-name\u003e -n flux-system\n\n# If your GitHub token expires, update the Flux secret\n# Generate base64 encoded token\necho -n 'ghp_yourNewTokenHere' | base64\n\n# Edit the secret and replace data.password with the new base64 value\nkubectl edit secret flux-system -n flux-system\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreistefanciprian%2Furlshortener-gitops","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandreistefanciprian%2Furlshortener-gitops","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreistefanciprian%2Furlshortener-gitops/lists"}