Complete reference for all automation scripts in Charon. All scripts are located
in the scripts/ directory and are called by Terraform during deployment.
- cert-manager Scripts
- DNS Management Scripts
- FreeIPA Scripts
- Headscale Scripts
- Tailscale Scripts
- Redmine Scripts
Creates Kubernetes secret for Cloudflare API token used by cert-manager DNS-01 challenge.
Usage:
python scripts/cert-manager/create_cloudflare_secret.pyEnvironment Variables:
CLOUDFLARE_API_TOKEN- Cloudflare API token with DNS edit permissions
Called By: Terraform during cert-manager setup
Waits for cert-manager pods to be ready before proceeding with certificate creation.
Usage:
python scripts/cert-manager/wait_for_cert_manager.py --namespace cert-managerParameters:
--namespace- cert-manager namespace (default:cert-manager)--timeout- Maximum wait time in seconds (default: 300)
Called By: Terraform after cert-manager deployment
Waits for wildcard certificate to be provisioned and ready.
Usage:
python scripts/cert-manager/wait_for_wildcard_cert.py \
--namespace dev \
--cert-name wildcard-example-com-tlsParameters:
--namespace- Namespace containing the certificate--cert-name- Name of the certificate resource--timeout- Maximum wait time in seconds (default: 600)
Called By: Terraform after certificate resource creation
Updates Cloudflare DNS A records for services with automatic stale record cleanup.
Key Features:
- Resilient fallback to node IPs if pod VPN IP not available
- Automatic cleanup of stale DNS records from old/offline pods
- Multi-record detection and management
- Batch service updates
Usage:
# Update single service
python scripts/dns/update_service_dns.py \
--zone-id ZONE_ID \
--namespace dev \
--services '[{"name":"grafana","hostname":"grafana","record_name":"grafana","enabled":true}]'
# Initial VPN DNS setup
python scripts/dns/update_service_dns.py \
--zone-id ZONE_ID \
--namespace dev \
--initial-vpn-dnsParameters:
--zone-id- Cloudflare Zone ID--api-token- Cloudflare API token (or useCLOUDFLARE_API_TOKENenv var)--namespace- Kubernetes namespace--services- JSON array of service configurations--initial-vpn-dns- Create initial VPN DNS records with node IPs--dry-run- Test without making changes
Service JSON Format:
{
"name": "service-name",
"hostname": "service-hostname",
"record_name": "dns-record-name",
"enabled": true
}Called By: Terraform post-deployment per-service DNS updates
Self-Healing Behavior:
- Detects multiple A records for same hostname
- Keeps record matching current pod IP
- Deletes stale records from old/offline pods
- Creates new record if none match current IP
Zone-wide cleanup that removes ALL DNS A records not matching current online Headscale nodes.
Usage:
python scripts/dns/prune_dns_records.py \
--zone-id ZONE_ID \
--namespace dev \
--grace-period 300Parameters:
--zone-id- Cloudflare Zone ID--api-token- Cloudflare API token--namespace- Kubernetes namespace with Headscale--grace-period- Seconds to wait before deleting (default: 300)--dry-run- Test without making changes
Called By: Manual maintenance or scheduled jobs
Warning: More aggressive than update_service_dns.py - removes ANY A record
not matching current Headscale nodes. Use with caution.
Manually delete specific DNS A records.
Usage:
python scripts/dns/delete_a_record.py \
--zone-id ZONE_ID \
--record-id RECORD_IDParameters:
--zone-id- Cloudflare Zone ID--record-id- Cloudflare DNS record ID to delete--api-token- Cloudflare API token
Called By: Manual cleanup operations
Initializes FreeIPA server with domain, realm, and admin password.
Usage:
python scripts/freeipa/init_freeipa.pyEnvironment Variables:
FREEIPA_ADMIN_PASSWORD- Admin password for FreeIPAFREEIPA_DOMAIN- FreeIPA domain (e.g.,dev.svc.cluster.local)FREEIPA_REALM- Kerberos realm (e.g.,DEV.SVC.CLUSTER.LOCAL)
Called By: Terraform after FreeIPA pod starts
Configures FreeIPA settings, groups, and policies.
Usage:
python scripts/freeipa/configure_freeipa.py --namespace devParameters:
--namespace- Kubernetes namespace with FreeIPA pod
Environment Variables:
FREEIPA_ADMIN_PASSWORD- Admin password
Called By: Terraform after FreeIPA initialization
Configuration Applied:
- Creates user groups
- Sets password policies
- Configures LDAP settings
- Sets up authentication policies
Creates FreeIPA users from JSON configuration file with automatic 1-year password expiration.
Usage:
python scripts/freeipa/create_users.py \
--namespace dev \
--users-file scripts/freeipa/freeipa_users.jsonParameters:
--namespace- Kubernetes namespace--users-file- Path to users JSON file
Environment Variables:
FREEIPA_ADMIN_PASSWORD- Admin password
Users JSON Format:
[
{
"username": "user1",
"first_name": "First",
"last_name": "Last",
"email": "user1@example.com",
"password": "initial-password",
"groups": ["admins"]
}
]Called By: Terraform after FreeIPA configuration
Features:
- Automatically sets password expiration to 1 year from creation
- Prevents immediate password expiration issues
- Adds users to specified groups
Waits for Headscale pod to be ready and API to be accessible.
Usage:
python scripts/headscale/wait_for_headscale.py --namespace devParameters:
--namespace- Kubernetes namespace--timeout- Maximum wait time in seconds (default: 300)
Called By: Terraform after Headscale deployment
Generates or retrieves Headscale API key and stores in Kubernetes secret.
Usage:
python scripts/headscale/get_headscale_api_key.py --namespace devParameters:
--namespace- Kubernetes namespace
Called By: Terraform after Headscale is ready
Creates:
- Kubernetes secret
headscale-api-keywith API key
Creates Headscale user and generates pre-auth key for service enrollment.
Usage:
python scripts/headscale/create_headscale_user_and_key.py \
--namespace dev \
--user default \
--expiration 90dParameters:
--namespace- Kubernetes namespace--user- Headscale user name--expiration- Key expiration (e.g.,90d,1y)--reusable- Make key reusable (flag)
Called By: Terraform when creating service-specific auth keys
Output: Pre-auth key for Tailscale enrollment
Removes offline Headscale nodes to prevent IP accumulation and stale DNS records.
Usage:
python scripts/headscale/cleanup_headscale_nodes.py \
--namespace dev \
--offline-threshold 3600Parameters:
--namespace- Kubernetes namespace--offline-threshold- Seconds offline before deletion (default: 3600)
Called By: Terraform post-deployment cleanup (centralized)
What It Does:
- Lists all Headscale nodes
- Identifies nodes offline longer than threshold
- Deletes offline nodes to free VPN IPs
- Prevents DNS records for non-existent pods
Generates Tailscale auth key for service VPN enrollment.
Usage:
python scripts/tailscale/get_tailscale_key.py \
--namespace dev \
--service-name grafanaParameters:
--namespace- Kubernetes namespace--service-name- Service name for key--expiration- Key expiration (default:90d)
Called By: Terraform when deploying services with Tailscale sidecars
Creates:
- Kubernetes secret
{service}-tailscale-authwith auth key
Backup and restore Redmine PostgreSQL database.
Usage:
# Backup database
python scripts/redmine/backup_restore_db.py backup
# Restore from backup
python scripts/redmine/backup_restore_db.py restore --file redmine_backup_20241110_143000.sqlCommands:
backup- Create timestamped SQL backup filerestore- Restore database from SQL file
Parameters:
--file- Backup file path (restore only)--output-dir- Backup directory (default:./backups)
Environment Variables:
REDMINE_DB_HOST- PostgreSQL hostREDMINE_DB_PORT- PostgreSQL portREDMINE_DB_NAME- Database nameREDMINE_DB_USER- Database userREDMINE_DB_PASSWORD- Database password
Called By: Manual operations or scheduled backup jobs
Features:
- Secure
.pgpassfile for authentication - Timestamped backup files
- Automatic cleanup of temporary files
Tests Redmine database connection.
Usage:
python scripts/redmine/test_connection.pyEnvironment Variables:
REDMINE_DB_HOSTREDMINE_DB_PORTREDMINE_DB_NAMEREDMINE_DB_USERREDMINE_DB_PASSWORD
Called By: Manual testing or troubleshooting
Mirrors documentation to Redmine wiki pages.
Usage:
python scripts/redmine/mirror_docs.py \
--redmine-url https://redmine.example.com \
--api-key YOUR_API_KEYParameters:
--redmine-url- Redmine instance URL--api-key- Redmine API key--docs-dir- Documentation directory (default:./docs)
Called By: Manual documentation sync operations
All scripts follow these patterns:
- Exit code 0 on success
- Exit code 1 on failure
- Descriptive error messages to stderr
- JSON output for structured data
Scripts use kubectl for Kubernetes operations:
- Namespace-aware operations
- Pod status checking
- Secret management
- ConfigMap updates
Many scripts support --dry-run flag:
- Shows what would be done without making changes
- Useful for testing and validation
- Safe for experimentation
Navigation: Documentation Index | Home