GitHub Actions - Technology Guide¶
This guide explains what GitHub Actions is, how the workflows in this homelab work, and how to use them for deployment and automation. No prior CI/CD experience required.
What is GitHub Actions?¶
GitHub Actions is GitHub's built-in CI/CD (Continuous Integration / Continuous Deployment) platform. It allows you to automate tasks that run in response to events in your GitHub repository (like pushing code) or manually.
In this homelab, GitHub Actions workflows automate:
- Running OpenTofu to create/update infrastructure
- Running Ansible playbooks to configure servers
- Deploying Kubernetes manifests
Why use GitHub Actions instead of running commands manually?
- Secrets are managed centrally (Bitwarden SM → GitHub Actions)
- No need to install tools locally (OpenTofu, Ansible, kubectl)
- Reproducible - the same steps run the same way every time
- Audit trail - every workflow run is logged with inputs and outputs
- Safe - credentials are never exposed in logs (masked automatically)
References:
Key Concepts¶
Workflow¶
A workflow is a YAML file stored in .github/workflows/ that defines automated
processes. Each workflow has:
- Triggers - events that cause the workflow to run
- Jobs - groups of steps that run together
- Steps - individual commands or actions
Triggers¶
Common triggers in this homelab:
on:
# Runs when code is pushed to main branch (only if opentofu/ files changed)
push:
branches: [main]
paths: ["opentofu/**"]
# Runs when a pull request is opened (for review)
pull_request:
branches: [main]
paths: ["opentofu/**"]
# Can be triggered manually from the GitHub UI
workflow_dispatch:
inputs:
target_host:
description: "Target hostname"
required: true
workflow_dispatch is used for all Ansible workflows - they require manual trigger
because they need a target_host input.
Jobs and Steps¶
jobs:
deploy:
runs-on: ubuntu-latest # Run on GitHub's cloud runners
steps:
- name: Checkout code
uses: actions/checkout@v6 # Clone the repository
- name: Do something
run: echo "Hello from CI" # Run a shell command
Actions¶
Actions are reusable, pre-built steps. They are referenced with uses::
| Action | What It Does |
|---|---|
actions/checkout@v6 |
Clones the repository into the runner |
bitwarden/sm-action@v2 |
Pulls secrets from Bitwarden Secrets Manager |
tailscale/github-action@v3 |
Connects the runner to the Tailscale tailnet |
opentofu/setup-opentofu@v2 |
Installs OpenTofu on the runner |
Secrets¶
GitHub Actions repository secrets are encrypted values stored in the repository settings. They are injected as environment variables in workflows.
In this homelab, only ONE secret is stored directly in GitHub:
BW_ACCESS_TOKEN- used to pull all other secrets from Bitwarden SM
All other secrets live in Bitwarden SM and are fetched at runtime.
How to Trigger a Workflow Manually¶
- Go to github.com/hexabyte8/homelab
- Click the Actions tab
- Find the workflow in the left sidebar (e.g., "Ansible - Deploy k3s")
- Click Run workflow on the right side
- Fill in any required inputs
- Click Run workflow button
Reading Workflow Logs¶
When a workflow runs:
- Click on the workflow run in the Actions tab
- Click on a job name to expand it
- Click on any step to see its output
Important: Sensitive values (secrets) are automatically replaced with *** in logs.
Job Summaries¶
Many workflows post a job summary - a formatted report shown at the bottom of the workflow run page. These summaries include:
- What was applied
- Any errors
- Output from tools like
tofu plan
Common Issues¶
Workflow fails at "Get Secrets" step¶
The BW_ACCESS_TOKEN GitHub secret is missing or invalid:
- Check Settings → Secrets and variables → Actions that
BW_ACCESS_TOKENexists - Log in to Bitwarden SM and verify the token is not expired
- Create a new token if needed and update the GitHub secret
Tailscale connection fails¶
The OAuth client credentials have issues:
- Check the Tailscale admin console for the CI OAuth client
- Verify the credentials in Bitwarden SM are correct
- Re-generate OAuth client credentials if needed
Ansible "SSH connection failed"¶
- Verify the target VM is online: check Tailscale admin console
- Verify the VM hostname is correct in the workflow input
- Check if cloud-init completed successfully on the VM:
Terraform plan shows unexpected changes¶
This can happen if:
- Resources were modified outside Terraform
- The Terraform state is out of sync with reality
Run tofu plan and review the output carefully before tofu apply.
workflow_dispatch not available¶
If you don't see the Run workflow button:
- Ensure you are on the
mainbranch in the UI - Ensure the workflow file has
workflow_dispatch:in itson:section - Wait a few minutes after pushing the workflow file - GitHub needs to index it
Secrets Flow Summary¶
graph TD
bw["Bitwarden Secrets Manager"] -->|"pulled via BW_ACCESS_TOKEN"| runner["GitHub Actions Runner<br/><br/>PM_API_TOKEN_ID<br/>PM_API_TOKEN_SECRET<br/>CLOUDFLARE_API_TOKEN<br/>TAILSCALE_OAUTH_CLIENT_ID<br/>TAILSCALE_OAUTH_CLIENT_SECRET<br/>AWS_ACCESS_KEY_ID<br/>AWS_SECRET_ACCESS_KEY<br/>... etc."]
runner -->|"authenticates to"| tf["OpenTofu/Terraform<br/>• S3 state backend (AWS)<br/>• Proxmox (PM_API_TOKEN)<br/>• Cloudflare (API token)<br/>• Tailscale (API key)"]
runner -->|"SSH over Tailscale"| ansible["Ansible<br/>• Configure k3s nodes<br/>• Deploy services"]