maceosoft Platform — GitHub¶
How the GitHub org maceosoft connects to the HomeLab cluster:
- Argo CD deploys from the private repo maceosoft/gitops.
- ARC (Actions Runner Controller) runs a self-hosted GitHub Actions runner inside the cluster
(one scale set per organization: arc-runners for maceosoft and arc-runners-symintel for the legacy org; see
Two organizations).
- OpenTofu manages the org from a pipeline that runs on one of those
runners, and stores its state in the cluster.
Where it runs in the implementation guide
- Steps 1 and 2 (manual): Phase 0 — GitHub and 1Password
- Step 3 (platform secrets): Phase 4 — 4.2, before the bootstrap ApplicationSet
- Steps 4 and 5 (ARC and pipeline): Phase 4 — 4.11
This page is the complete reference: permissions, fields, verification, and rotation.
Repos involved
| Repo | What it contains |
|---|---|
maceosoft/homelab |
This site. Ansible: k3s, Argo CD, and platform secrets (1Password → cluster) |
maceosoft/gitops |
Argo CD Applications, including ARC and the OpenTofu runner |
maceosoft/core-pipelines |
Reusable workflows (tofu.yml, CI, FTP deploy) |
maceosoft/infra |
OpenTofu: org repos, environments, and secrets |
How it fits¶
flowchart LR
OP[1Password<br/>bóveda HomeLab] -->|playbook-platform-secrets.yml| K8S
subgraph K8S[Clúster k3s]
ARGO[ArgoCD] -->|App maceosoft-argocd| GITOPS[(maceosoft/gitops)]
ARGO --> ARC[ARC controller]
ARC --> RT[arc-runners]
RT --> STATE[(ns terraform<br/>Secret tfstate-default-github)]
end
INFRA[maceosoft/infra] -->|tofu.yml de core-pipelines| RT
RT -->|App maceosoft-terraform| GH[org maceosoft]
Some pieces must exist before Argo CD or the pipeline can work. Those are created by hand, once, and OpenTofu neither manages nor imports them:
| What | Why manual |
|---|---|
Repos gitops, infra, core-pipelines |
Without them there's nowhere to deploy from and no pipeline to run OpenTofu |
App maceosoft-argocd |
Argo CD needs it to read the private repo that deploys everything else |
| GitHub Apps and OAuth App | GitHub doesn't allow creating OAuth Apps via API, and GitHub Apps require browser confirmation |
Everything else (repo api and future repos) is created by the
infra pipeline.
1Password Items¶
All in the HomeLab vault. Scripts read them through the 1Password
desktop app, which must be unlocked and have Settings →
Developer → Integrate with other apps enabled. To indicate which account
to use, define ONEPASSWORD_ACCOUNT_NAME with your account name as it appears
in the top left of the app sidebar (for example Mi Cuenta; if not defined, it uses Personal):
| Item | Item type | Fields | Used by |
|---|---|---|---|
maceosoft-terraform |
Secure Note | app_id, installation_id, private_key |
OpenTofu runner (TF_VAR_github_app_*) |
maceosoft-arc-runners |
Secure Note | app_id, installation_id, private_key |
ARC (runner registration) |
maceosoft-argocd |
Secure Note | app_id, installation_id, private_key |
Argo CD reads maceosoft/gitops (argocd/repo-gitops) |
symintel-arc-runners (optional) |
Secure Note | app_id, installation_id, private_key |
ARC for the legacy org (symintel): its scale set registration. See Two organizations |
symintel-terraform (optional) |
Secure Note | app_id, installation_id, private_key |
OpenTofu for the legacy org; without it, those runners lack OpenTofu credentials |
sealed-secrets |
Secure Note | certificate, private_key (optional until Phase 6) |
Sealed Secrets encryption key: survives K3s reinstall |
maceosoft-dex |
Secure Note | GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET (+ VCLUSTER_CLIENT_SECRET, generated by the playbook) |
Dex (GitHub login) |
discord-webhooks |
Secure Note | critical, warnings: Discord webhook URL per channel; deployments (optional): the despliegues channel one for Argo CD notifications (optional: monitoring) |
Alertmanager sends alerts (4.13). How to create them: Discord and healthchecks.io |
healthchecks-ping |
Secure Note | url: healthchecks.io check ping URL (optional: monitoring) |
Alertmanager pings it every 5 minutes to signal monitoring is alive. How to create it: Discord and healthchecks.io |
grafana-admin |
Secure Note | password and, optionally, username (default admin) (optional: monitoring) |
Grafana admin |
ftp-<repo> |
Secure Note | dev_host, dev_user, dev_password, dev_remote_dir, prod_host, prod_user, prod_password, prod_remote_dir |
OpenTofu → <repo> FTP secrets (TF_VAR_ftp) |
How to create an item with custom fields¶
The playbook looks up each value by its path op://HomeLab/<item>/<campo>, so the item title and every field name must be exact (lowercase, with underscores).
- In 1Password open the
HomeLabvault → New Item → Secure Note. - In Title type the item name, for example
maceosoft-terraform. - For each field: + Add more → choose the type (Text or Password) → in the field label type the exact name (for example
app_id) → paste the value. - Add the fields directly on the item. Do not create a section to group them: with a section the path changes and the playbook won't find them.
- Save.
Use Password for secret values (they are hidden) and Text for the rest. Each table below tells which type each field uses.
You can also create the item with the 1Password CLI (op), with 1Password unlocked. Each field is written as nombre[tipo]=valor, where the type is password (secret value) or text; op creates loose fields, without a section. Secret values are not typed in the command: they are pasted without echo using read -rs:
# pega la contraseña y Enter (no se ve)
read -rs FTP_DEV_PASS
op item create --category "Secure Note" --vault HomeLab --title ftp-mi-repo \
"dev_host[text]=ftp.ejemplo.com" "dev_user[text]=usuario" "dev_password[password]=$FTP_DEV_PASS"
unset FTP_DEV_PASS
If you have more than one 1Password account, export OP_ACCOUNT with yours first. For a random value use $(openssl rand -hex 32). Local AI items (router tokens, Open Terminal…) already have their commands in Secrets Management.
Step 1 — GitHub Apps and OAuth App (manual)¶
Do this with an organization owner account maceosoft.
maceosoft-terraform¶
maceosoft → Settings → Developer settings → GitHub Apps → New GitHub App
| Field | Value |
|---|---|
| GitHub App name | maceosoft-terraform |
| Homepage URL | https://github.com/maceosoft |
| Webhook → Active | unchecked |
| Where can this GitHub App be installed? | Only on this account |
The rest of the form (Callback URL, Setup URL, Request user authorization, events) is left empty or unchecked.
| Repository permission | Access | Purpose |
|---|---|---|
| Actions | Read and write | Actions management in repos |
| Administration | Read and write | Create repos and branch protection |
| Contents | Read and write | Repo files |
| Environments | Read and write | Environments dev / prod |
| Metadata | Read-only | Required |
| Secrets | Read and write | FTP secrets per environment |
| Variables | Read and write | PROJECT_STACK, FTP_PROTOCOL |
| Workflows | Read and write | .github/workflows/* files |
| Organization permission | Access | Purpose |
|---|---|---|
| Administration | Read and write | Create repos in the org |
All other permissions remain at No access.
After Create GitHub App, gather three pieces of data and save them in the maceosoft-terraform item in 1Password (Secure Note, see how to create it):
| Field in 1Password | Type | Data | Where in GitHub |
|---|---|---|---|
app_id |
Text | App ID | App page, General tab: App ID line (a number, e.g. 1234567) |
private_key |
Password | Private key | Same page, bottom under Private keys → Generate a private key. A maceosoft-terraform.<fecha>.private-key.pem file downloads. Open it with a text editor and copy everything, including the -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY----- lines |
installation_id |
Text | Installation ID | App left menu → Install App → Install next to maceosoft → All repositories → Install. GitHub takes you to https://github.com/organizations/maceosoft/settings/installations/<número>: that final number |
The item looks like this:
maceosoft-terraform (Nota segura · bóveda HomeLab)
├── app_id 1234567
├── installation_id 87654321
└── private_key •••••••• (el .pem completo)
Done only from the web: create the App, generate its private key (Generate a private key) and install it. GitHub offers no CLI or API for this (manifest-based App creation also requires browser confirmation). Saving the data in 1Password can be done either way:
When pasting the .pem into a Password field, line breaks are lost. Doesn't matter: the playbook reconstructs the key. Once the item is saved, delete the .pem from Downloads.
What is automated is reading the two numbers and saving the item.
-
List installed Apps in the org and extract
App IDandInstallation ID(needs the organization permission:gh auth refresh -s admin:read:orgonce): -
With the downloaded
.pem, create the item (1Password unlocked; if you have more than one 1Password account, exportOP_ACCOUNTfirst). The.pemvalue is read from the file and never typed in the command:APP=maceosoft-terraform read -r APP_ID INST_ID < <(gh api orgs/maceosoft/installations \ --jq ".installations[] | select(.app_slug==\"$APP\") | \"\(.app_id) \(.id)\"") op item create --category "Secure Note" --vault HomeLab --title "$APP" \ "app_id[text]=$APP_ID" "installation_id[text]=$INST_ID" \ "private_key[password]=$(cat ~/Downloads/$APP.*.private-key.pem)" -
Verify without showing values and delete the
.pem:
The same command works for the other Apps: just change APP (maceosoft-arc-runners, maceosoft-argocd, and symintel-arc-runners / symintel-terraform if using the old org, changing orgs/maceosoft to orgs/symintel).
maceosoft-arc-runners¶
This is the App ARC uses to register the runner arc-runners in the org. It is created in the same form as maceosoft-terraform, but it is a separate App: its own name, permissions, and credentials.
maceosoft → Settings → Developer settings → GitHub Apps → New GitHub App
| Field | Value |
|---|---|
| GitHub App name | maceosoft-arc-runners |
| Homepage URL | https://github.com/maceosoft |
| Webhook → Active | unchecked |
| Where can this GitHub App be installed? | Only on this account |
The rest of the form (Callback URL, Setup URL, Request user authorization, events) is left empty or unchecked.
| Repository permission | Access | Purpose |
|---|---|---|
| Actions | Read-only | View queued jobs the runner must pick up |
| Administration | Read and write | Register runners (requested by ARC) |
| Metadata | Read-only | Required |
| Organization permission | Access | Purpose |
|---|---|---|
| Self-hosted runners | Read and write | Register and delete the runner arc-runners in the org |
All other permissions remain at No access.
After Create GitHub App, save its three pieces of data in the maceosoft-arc-runners item in 1Password (Secure Note, see how to create it):
| 1Password field | Type | Data | Where in GitHub |
|---|---|---|---|
app_id |
Text | App ID | App page, General tab: App ID line |
private_key |
Password | Private key | Same page, bottom under Private keys → Generate a private key. Downloads maceosoft-arc-runners.<fecha>.private-key.pem. Open with a text editor and copy everything, including the -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY----- lines |
installation_id |
Text | Installation ID | App left menu → Install App → Install next to maceosoft → All repositories → Install. The number at the end of the URL https://github.com/organizations/maceosoft/settings/installations/<número> |
The item looks like this:
maceosoft-arc-runners (Nota segura · bóveda HomeLab)
├── app_id 2345678
├── installation_id 98765432
└── private_key •••••••• (el .pem completo)
Creating the App, its key, and installing it is only done from the web; saving the item can be done either way:
The three values are different from those of maceosoft-terraform: each App has its own App ID, its own key, and its own installation. Do not copy the ones from the other App. Once the item is saved, delete the .pem from Downloads.
The same maceosoft-terraform command with APP=maceosoft-arc-runners: gh api outputs this App's numbers, so they don't get mixed up with the other one.
APP=maceosoft-arc-runners
read -r APP_ID INST_ID < <(gh api orgs/maceosoft/installations \
--jq ".installations[] | select(.app_slug==\"$APP\") | \"\(.app_id) \(.id)\"")
op item create --category "Secure Note" --vault HomeLab --title "$APP" \
"app_id[text]=$APP_ID" "installation_id[text]=$INST_ID" \
"private_key[password]=$(cat ~/Downloads/$APP.*.private-key.pem)"
python3 ansible/scripts/apply_platform_secrets.py --check
# en macOS: rm -P
shred -u ~/Downloads/$APP.*.private-key.pem
OAuth App Maceosoft Dex¶
maceosoft → Settings → Developer settings → OAuth Apps → New OAuth App
| Field | Value |
|---|---|
| Application name | Maceosoft Dex |
| Homepage URL | https://argocd.homelab.local |
| Redirect URIs | https://argocd.homelab.local/api/dex/callback (only this one) |
After Register application, create the maceosoft-dex item in the HomeLab vault (Secure Note, see how to create it) with these two fields:
| 1Password field | Type | Data | Where in GitHub |
|---|---|---|---|
GITHUB_CLIENT_ID |
Text | Client ID | OAuth App page: Client ID line |
GITHUB_CLIENT_SECRET |
Password | Client secret | Same page → Generate a new client secret. GitHub shows it only once: copy it at that moment |
The item looks like this (the last field is added automatically by playbook-dex-oauth-secrets.yml the first time it runs: it's the vCluster Dex client secret, not from GitHub):
maceosoft-dex (Nota segura · bóveda HomeLab)
├── GITHUB_CLIENT_ID Ov23li…
├── GITHUB_CLIENT_SECRET ••••••••
└── VCLUSTER_CLIENT_SECRET •••••••• (lo genera el playbook)
Creating the OAuth App and generating its client secret is only done from the web: GitHub has no API for OAuth Apps. Saving the two values in 1Password can be done either way:
Create the Secure Note maceosoft-dex and paste each value from the table into its field (how to create it).
Once you have the two values, save them without displaying them on screen (if you have more than one 1Password account, export OP_ACCOUNT first):
To verify someone is in the team devops (or add them) from the console:
gh api orgs/maceosoft/teams/devops/memberships/<usuario> (returns "state": "active") and, to add them as a member,
gh api -X PUT orgs/maceosoft/teams/devops/memberships/<usuario> -f role=member.
Only the devops team from maceosoft can enter, and its members become Argo CD admins. This is applied in Phase 4 step 4.7.
Step 2 — Repos, Argo CD App & FTP (manual)¶
-
Repos (private), created in
maceosoftwith their content pushed via git:gitops.core-pipelines: afterwards, make it accessible to the other repos in the org (below). While testing, the other repos use it with@main; the tagv1is created once everything works (see the README ofcore-pipelines).infra.
Create each repo in the org with New repository (private) and push its content with git. Then, in
core-pipelines: Settings → Actions → General → Access, choose "Accessible from repositories in the 'maceosoft' organization".With the GitHub CLI, from each project's folder:
gh repo create maceosoft/gitops --private --source . --remote origin --push # igual para core-pipelines e infra gh repo list maceosoft --json name,visibility --jq '.[] | [.name, .visibility] | @tsv' # core-pipelines accesible desde los demás repos de la org gh api -X PUT repos/maceosoft/core-pipelines/actions/permissions/access -f access_level=organization- GitHub App
maceosoft-argocd, used by Argo CD to read the private repogitops. Comes after the repos because it is installed only ongitops. (Deploy keys are disabled in the organization, so an App is used.)
maceosoft → Settings → Developer settings → GitHub Apps → New GitHub App
Field Value GitHub App name maceosoft-argocdHomepage URL https://github.com/maceosoftWebhook → Active unchecked Where can this GitHub App be installed? Only on this account The rest of the form is left empty or unchecked.
Repository permission Access Purpose Contents Read-only Clone the repo Metadata Read-only Required No organization permissions. All others remain No access.
After Create GitHub App, save its three pieces of data in the
maceosoft-argocditem in 1Password (Secure Note, see how to create it):1Password field Type Data Where in GitHub app_idText App ID App page, General tab: App ID line private_keyPassword Private key Same page, bottom under Private keys → Generate a private key. Copy the entire downloaded .pem, including theBEGIN/ENDlinesinstallation_idText Installation ID Left menu → Install App → Install next to maceosoft→ Only select repositories → choosegitops→ Install. The number at the end of the URL…/settings/installations/<número>Install it only on
gitops: with that key you can read the code of all repos where it is installed. Delete the.pemwhen finished.Creating the App, its key, and installing it is web-only; saving the item can be done either way:
Create the Secure Note
maceosoft-argocdand paste each piece of data from the table into its field (how to create it).The same command from
maceosoft-terraform, withAPP=maceosoft-argocd:APP=maceosoft-argocd read -r APP_ID INST_ID < <(gh api orgs/maceosoft/installations \ --jq ".installations[] | select(.app_slug==\"$APP\") | \"\(.app_id) \(.id)\"") op item create --category "Secure Note" --vault HomeLab --title "$APP" \ "app_id[text]=$APP_ID" "installation_id[text]=$INST_ID" \ "private_key[password]=$(cat ~/Downloads/$APP.*.private-key.pem)" # en macOS: rm -P shred -u ~/Downloads/$APP.*.private-key.pem -
FTP (File Transfer Protocol) credentials for repo
api, the first project in the map withdeploy = true: titleftp-api, type Secure Note. For each repo you add later, follow the procedure — Add a repo. Fields, created the same way as the others:Field Type Example dev_hostText dev.tu-cpanel.example.comdev_userText usuario_devdev_passwordPassword dev_remote_dirText /home/usuario/dev.maceosoft.example.comprod_hostText tu-cpanel.example.comprod_userText usuario_prodprod_passwordPassword prod_remote_dirText /home/usuario/public_htmlChange the hosts, users, and folders to yours; the two passwords are pasted without echo (if you have more than one 1Password account, export
OP_ACCOUNTfirst):# pega cada contraseña y Enter read -rs FTP_DEV_PASS; read -rs FTP_PROD_PASS op item create --category "Secure Note" --vault HomeLab --title ftp-api \ "dev_host[text]=dev.tu-cpanel.example.com" "dev_user[text]=usuario_dev" \ "dev_password[password]=$FTP_DEV_PASS" "dev_remote_dir[text]=/home/usuario/dev.maceosoft.example.com" \ "prod_host[text]=tu-cpanel.example.com" "prod_user[text]=usuario_prod" \ "prod_password[password]=$FTP_PROD_PASS" "prod_remote_dir[text]=/home/usuario/public_html" unset FTP_DEV_PASS FTP_PROD_PASS -
Sealed Secrets key (optional: needed when you start storing
SealedSecretin Git, e.g., in Phase 6). Sealed Secrets encrypts secrets with a key pair that, by default, the controller generates inside the cluster: if you reinstall K3s it is lost, and theSealedSecretalready in Git can no longer be decrypted. That's why it is generated once, saved in 1Password, and the secrets playbook brings it to the cluster before the controller starts.Generate the pair in a temporary folder (
opensslships with macOS and Linux):cd "$(mktemp -d)" openssl req -x509 -days 3650 -nodes -newkey rsa:4096 \ -keyout tls.key -out tls.crt -subj "/CN=sealed-secret/O=sealed-secret"Create in 1Password the item
sealed-secrets(Secure Note, created the same way as the others):Field Type Value certificateText The full content of tls.crt(the public key), with the-----BEGIN CERTIFICATE-----and-----END CERTIFICATE-----linesprivate_keyPassword The full content of tls.key(the private key), with itsBEGIN/ENDlinesTo copy a file:
pbcopy < tls.crt(macOS) or open it with an editor and copy everything.With the 1Password CLI the files are read directly (if you have more than one 1Password account, export
OP_ACCOUNTfirst):Once the item is saved, delete the files:
The certificate is valid for 10 years. The playbook verifies that the certificate and key are a pair (if you copied files from different pairs, it stops with a clear message) and creates the Secret
kube-system/sealed-secrets-key-homelab, which the controller detects by its labelsealedsecrets.bitnami.com/sealed-secrets-key: active. While the item doesn't exist, the playbook warns and continues: Sealed Secrets would generate its own key.
Step 3 — Cluster and platform secrets¶
With k3s installed (Phase 3, Argo CD included):
# tu cuenta
export ONEPASSWORD_ACCOUNT_NAME="Mi Cuenta"
export ONEPASSWORD_VAULT="HomeLab"
cd ansible
ansible-playbook -i inventory.ini playbook-platform-secrets.yml
playbook-platform-secrets.yml
creates the namespaces argocd, arc-runners (PSS privileged, for the dind sidecar) and terraform
(only stores OpenTofu state), and these Secrets:
| Secret | Namespace | Content |
|---|---|---|
repo-gitops |
argocd |
App maceosoft-argocd: Argo CD can clone https://github.com/maceosoft/gitops.git |
arc-runners-github-app |
arc-runners |
ARC App |
terraform-app |
arc-runners |
TF_VAR_github_app_id, TF_VAR_github_app_installation_id, TF_VAR_github_app_private_key |
tofu-vars |
arc-runners |
TF_VAR_ftp (all ftp-<repo> items) |
arc-runners-github-app, terraform-app |
arc-runners-symintel |
Same for the old org, from symintel-arc-runners and symintel-terraform (only if they exist). The namespace is created with PSS baseline |
sealed-secrets-key-homelab |
kube-system |
Sealed Secrets key pair (item sealed-secrets, if exists) |
discord-webhooks, healthchecks-ping, grafana-admin |
monitoring |
Discord webhooks, healthchecks.io ping URL, and Grafana password (items with the same names; only if all three exist). The namespace is created with PSS privileged, because node-exporter uses the node's disk and network |
Single runner
It's a HomeLab: the single scale set (arc-runners, Default group) runs CI (continuous integration),
deploys and OpenTofu, and has the OpenTofu credentials as environment
variables. Any maceosoft repo that runs a job there can
reach them. Keep the org with only your repos.
Always against the HomeLab
The playbook uses ~/.kube/homelab-k3s.yaml (the one left by
k3s_fetch_kubeconfig), not the current kubectl context. This way it
doesn't write secrets to another cluster. For another kubeconfig:
-e platform_kubeconfig=/ruta.
It's idempotent: run it again whenever you rotate something in 1Password or add a
ftp-<repo> item.
Two organizations: one scale set per org¶
An ARC scale set registers with a single GitHub organization (githubConfigUrl). For the same runners to
serve the new org (maceosoft) and the old org (symintel) there are two scale sets, with a single controller
(arc-controller) serving both:
Org maceosoft |
Org symintel (old) |
|
|---|---|---|
| Application | arc-runners |
arc-runners-symintel |
| Namespace | arc-runners |
arc-runners-symintel |
| ARC App (1Password item) | maceosoft-arc-runners |
symintel-arc-runners |
Name in runs-on: |
arc-runners |
arc-runners (the same) |
Cache /cache (RWX, Longhorn) |
20 GiB | 10 GiB, separate |
Docker (dind) |
Yes, with a privileged sidecar | Yes, the same |
| OpenTofu and FTP | Yes (terraform-app, tofu-vars) |
Only if item symintel-terraform exists |
Both use the same runner template
(values-scaleset.yaml); the old org changes
githubConfigUrl (values-scaleset-symintel.yaml).
Each namespace has its own Secrets, with the same name, so those of one org aren't visible to the other, and the cache isn't
shared either (a poisoned cache in one org doesn't reach the other).
To enable the old org: create the ARC App in symintel (same as maceosoft-arc-runners, but in that
org) and save it in item symintel-arc-runners; then run playbook-platform-secrets.yml. If the item doesn't exist, the script doesn't
create the namespace or the Secret and the old org's scale set doesn't start. To remove it, delete the Application
arc-runners-symintel and the items.
Step 4 — GitOps¶
Argo CD syncs, among others, these Applications:
| Application | What it deploys |
|---|---|
arc-controller |
ARC Controller (arc-systems) |
terraform-rbac |
ServiceAccount tofu-runner + Role (only Secrets/Leases from namespace terraform) |
arc-runners |
The runner (up to 3 in parallel), with namespace Secrets as environment variables |
Step 5 — First OpenTofu pipeline¶
Push to main of infra, or trigger it from Actions → tofu →
Run workflow (with the CLI: gh workflow run tofu.yml --repo maceosoft/infra --ref main and gh run watch --repo maceosoft/infra). The workflow
tofu.yml
runs on arc-runners: it does plan on PRs (pull requests) and apply on main. On the
first run it creates api.
Verify¶
Before the cluster, ensure 1Password has everything (from the root of homelab):
# tu cuenta
export ONEPASSWORD_ACCOUNT_NAME="Mi Cuenta"
# items y campos: todo ✓
.venv/bin/python ansible/scripts/apply_platform_secrets.py --check
# Secrets que se van a crear, sin valores
.venv/bin/python ansible/scripts/apply_platform_secrets.py --dry-run
After the playbook and GitOps:
kubectl -n argocd get secret repo-gitops
kubectl -n arc-runners get secret \
arc-runners-github-app terraform-app tofu-vars
# org antigua, si la usas:
kubectl -n arc-runners-symintel get secret arc-runners-github-app
kubectl -n argocd get applications | grep -E 'arc|terraform'
# controller + listener del scale set
kubectl -n arc-systems get pods
# después del primer apply de OpenTofu
kubectl -n terraform get secret tfstate-default-github
Rotate credentials¶
Full step-by-step: Operations — Rotate credentials.
| What | How |
|---|---|
| Private key of a GitHub App | Generate a new one in GitHub (web only), replace private_key in 1Password (op item edit <item> "private_key[password]=$(cat llave.pem)"), re-run playbook-platform-secrets.yml and delete the old one in GitHub |
Private key of maceosoft-argocd |
Same as other Apps: new key in GitHub, replace private_key, re-run the playbook and delete the old one |
| FTP credentials | Edit ftp-<repo> (op item edit ftp-<repo> "prod_password[password]=..."), re-run the playbook and trigger the infra pipeline (gh workflow run tofu.yml --repo maceosoft/infra --ref main) |
| Discord webhook, healthchecks.io ping URL, or Grafana password | Change the field in its item, re-run playbook-platform-secrets.yml and follow Operations — Rotate credentials |
| Dex client secret | New secret in the OAuth App, update GITHUB_CLIENT_SECRET and run playbook-dex-oauth-secrets.yml |