GitHub Secrets Configuration Guide
Repository: orbit-rs
Purpose: Configure secrets for CI/CD pipeline deployment
Overview
The CI/CD pipeline (.github/workflows/ci-cd.yml) requires secrets to be configured in GitHub repository settings for Kubernetes deployments. This guide walks you through the setup process.
Required Secrets
1. KUBE_CONFIG_STAGING
Purpose: Kubernetes configuration for staging environment
Used by: deploy-staging job (runs on develop branch)
Format: Base64-encoded kubeconfig file
2. KUBE_CONFIG_PRODUCTION
Purpose: Kubernetes configuration for production environment
Used by: deploy-production job (runs on v* tags)
Format: Base64-encoded kubeconfig file
3. DOCKER_USERNAME (Optional)
Purpose: Docker Hub authentication for pushing images
Used by: docker-build job
Format: Docker Hub username string
4. DOCKER_PASSWORD (Optional)
Purpose: Docker Hub authentication token
Used by: docker-build job
Format: Docker Hub access token or password
Step-by-Step Configuration
Step 1: Access Repository Settings
- Navigate to your GitHub repository:
https://github.com/TuringWorks/orbit-rs - Click on Settings tab (requires admin access)
- In the left sidebar, navigate to Secrets and variables → Actions
Step 2: Prepare Kubernetes Configurations
For Staging Environment
-
Get your kubeconfig file:
# If using kubectl, your config is typically at: cat ~/.kube/config # Or get config for specific cluster: kubectl config view --minify --flatten > staging-kubeconfig.yaml -
Encode the kubeconfig:
# macOS/Linux: base64 < staging-kubeconfig.yaml | tr -d '\n' > staging-kubeconfig-base64.txt # Or in one command: cat staging-kubeconfig.yaml | base64 | tr -d '\n' -
Copy the base64 output (it will be a long string without line breaks)
For Production Environment
Repeat the same process for your production cluster:
kubectl config view --minify --flatten --context=production > production-kubeconfig.yaml
base64 < production-kubeconfig.yaml | tr -d '\n' > production-kubeconfig-base64.txt
Step 3: Add Secrets to GitHub
Add KUBE_CONFIG_STAGING
- In GitHub repository settings → Secrets and variables → Actions
- Click New repository secret
- Name:
KUBE_CONFIG_STAGING - Secret: Paste the base64-encoded staging kubeconfig
- Click Add secret
Add KUBE_CONFIG_PRODUCTION
- Click New repository secret again
- Name:
KUBE_CONFIG_PRODUCTION - Secret: Paste the base64-encoded production kubeconfig
- Click Add secret
Add Docker Hub Credentials (Optional)
If you want to push images to Docker Hub:
- Get Docker Hub Access Token:
- Go to https://hub.docker.com/settings/security
- Click New Access Token
- Name it
orbit-rs-ci-cd - Copy the token (you won’t be able to see it again)
- Add DOCKER_USERNAME:
- New repository secret
- Name:
DOCKER_USERNAME - Secret: Your Docker Hub username
- Add secret
- Add DOCKER_PASSWORD:
- New repository secret
- Name:
DOCKER_PASSWORD - Secret: Your Docker Hub access token
- Add secret
Step 4: Configure Environment Protection Rules (Recommended)
For additional security, set up environment protection:
- In repository Settings → Environments
- Click New environment (or select existing)
- Name:
staging(matches workflow environment name) - Configure protection rules:
- Required reviewers (optional): Add reviewers who must approve deployments
- Wait timer (optional): Add delay before deployment
- Deployment branches: Limit to
developbranch only
- Repeat for
productionenvironment:- Name:
production - Restrict to tags matching pattern:
v* - Add required reviewers (highly recommended for production)
- Name:
Alternative: Using Kubernetes Service Account (Recommended for Production)
Instead of using your personal kubeconfig, create a dedicated service account:
Create Service Account for Staging
# Create namespace
kubectl create namespace orbit-rs-staging
# Create service account
kubectl create serviceaccount orbit-deployer -n orbit-rs-staging
# Create role with deployment permissions
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: orbit-deployer-role
namespace: orbit-rs-staging
rules:
- apiGroups: ["", "apps", "batch"]
resources: ["deployments", "services", "pods", "configmaps", "secrets", "statefulsets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
EOF
# Bind role to service account
kubectl create rolebinding orbit-deployer-binding \
--role=orbit-deployer-role \
--serviceaccount=orbit-rs-staging:orbit-deployer \
-n orbit-rs-staging
# Create service account token
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: orbit-deployer-token
namespace: orbit-rs-staging
annotations:
kubernetes.io/service-account.name: orbit-deployer
type: kubernetes.io/service-account-token
EOF
# Get the token
kubectl get secret orbit-deployer-token -n orbit-rs-staging -o jsonpath='{.data.token}' | base64 -d
Generate Kubeconfig from Service Account
# Get cluster info
CLUSTER_NAME=$(kubectl config view -o jsonpath='{.contexts[?(@.name == "'$(kubectl config current-context)'")].context.cluster}')
CLUSTER_SERVER=$(kubectl config view -o jsonpath='{.clusters[?(@.name == "'${CLUSTER_NAME}'")].cluster.server}')
CLUSTER_CA=$(kubectl config view --flatten -o jsonpath='{.clusters[?(@.name == "'${CLUSTER_NAME}'")].cluster.certificate-authority-data}')
# Get service account token
SA_TOKEN=$(kubectl get secret orbit-deployer-token -n orbit-rs-staging -o jsonpath='{.data.token}' | base64 -d)
# Create kubeconfig
cat > staging-service-account-kubeconfig.yaml <<EOF
apiVersion: v1
kind: Config
clusters:
- name: ${CLUSTER_NAME}
cluster:
certificate-authority-data: ${CLUSTER_CA}
server: ${CLUSTER_SERVER}
contexts:
- name: orbit-deployer@${CLUSTER_NAME}
context:
cluster: ${CLUSTER_NAME}
namespace: orbit-rs-staging
user: orbit-deployer
current-context: orbit-deployer@${CLUSTER_NAME}
users:
- name: orbit-deployer
user:
token: ${SA_TOKEN}
EOF
# Encode for GitHub secret
base64 < staging-service-account-kubeconfig.yaml | tr -d '\n'
Repeat the same process for production with namespace orbit-rs or orbit-rs-production.
Verification
Test the Secrets
After adding secrets, verify they work:
- Manual workflow run:
- Go to Actions tab
- Select “CI/CD Pipeline”
- Click “Run workflow”
- Select branch/tag
- Run workflow
- Check deployment job:
- The deployment job should now run successfully
- Verify kubectl can connect to your cluster
- Check if Helm deployment succeeds
Common Issues
Issue: “error: You must be logged in to the server (Unauthorized)”
Solution:
- Token expired - regenerate service account token
- Wrong token format - ensure base64 encoding is correct
- Insufficient permissions - verify RBAC role has needed permissions
Issue: “Secret KUBE_CONFIG_STAGING is not set”
Solution:
- Ensure secret name matches exactly (case-sensitive)
- Secret must be in the repository where workflow runs
- Organization secrets need proper access configuration
Issue: Deployment fails with “connection refused”
Solution:
- Verify cluster server URL is accessible from GitHub Actions
- Check if cluster requires VPN or allowlisting GitHub IPs
- Consider using GitHub Actions self-hosted runners within your network
Security Best Practices
1. Use Service Accounts
Create dedicated service accounts for CI/CD
Grant minimal required permissions (principle of least privilege)
Rotate tokens regularly (every 90 days recommended)
2. Separate Environments
Use different secrets for staging and production
Use different namespaces or clusters
Never use production credentials in staging
3. Audit Access
Enable audit logging in Kubernetes
Monitor secret access in GitHub (Settings → Security log)
Review who has access to secrets regularly
4. Environment Protection
Require manual approval for production deployments
Limit deployment branches/tags
Add wait timers for production changes
5. Secret Rotation
Set expiration dates for service account tokens
Document rotation schedule
Automate rotation where possible
Secret Management Alternatives
Option 1: GitHub Environments with Environment Secrets
Instead of repository secrets, use environment-specific secrets:
- Settings → Environments → Create environment
- Add secrets to specific environment
- Workflow automatically uses environment secrets when deploying to that environment
Benefits:
- Automatic secret scoping by environment
- Better access control
- Clear separation between staging/production
Option 2: External Secret Management
For larger organizations, consider:
- HashiCorp Vault: Enterprise secret management
- AWS Secrets Manager: If using AWS
- Azure Key Vault: If using Azure
- Google Secret Manager: If using GCP
These can be integrated with GitHub Actions using official actions or custom scripts.
Option 3: Self-Hosted Runners
Deploy runners in your private network:
Benefits:
- Direct cluster access without exposing credentials
- Better security for sensitive environments
- Compliance with corporate policies
Setup:
- Settings → Actions → Runners → New self-hosted runner
- Follow installation instructions for your OS
- Runner can access Kubernetes cluster directly
Quick Reference Commands
# View current Kubernetes context
kubectl config current-context
# List available contexts
kubectl config get-contexts
# Switch context
kubectl config use-context <context-name>
# Get kubeconfig for specific context
kubectl config view --minify --flatten --context=<context-name>
# Test connection with specific kubeconfig
KUBECONFIG=./staging-kubeconfig.yaml kubectl get nodes
# Verify service account permissions
kubectl auth can-i create deployments --as=system:serviceaccount:orbit-rs-staging:orbit-deployer -n orbit-rs-staging
# List all secrets in namespace
kubectl get secrets -n orbit-rs-staging
# Decode secret
kubectl get secret <secret-name> -n orbit-rs-staging -o jsonpath='{.data.token}' | base64 -d
Support and Troubleshooting
GitHub Documentation
Kubernetes Documentation
Getting Help
- Check workflow logs in Actions tab for detailed error messages
- Review audit logs in repository settings
- Test locally with same kubeconfig before adding to GitHub
- Verify cluster connectivity from GitHub Actions IPs if needed
Checklist
Before running deployments, ensure:
- Kubernetes clusters are accessible
- Service accounts created with proper RBAC
- Kubeconfig files encoded correctly
- Secrets added to GitHub repository
- Environment protection rules configured
- Namespaces exist in clusters
- Helm charts tested locally
- Monitoring and alerting set up
- Rollback procedure documented
- Team members have necessary access
Maintained By: DevOps Team
Review Schedule: Quarterly
For questions or issues, contact the DevOps team or create an issue in the repository.