{"id":48903150,"url":"https://github.com/ainsleydev/platform","last_synced_at":"2026-04-16T17:02:04.103Z","repository":{"id":324898171,"uuid":"1098501523","full_name":"ainsleydev/platform","owner":"ainsleydev","description":"Platform Applications for Observability and Monitoring ","archived":false,"fork":false,"pushed_at":"2025-11-18T14:48:03.000Z","size":25,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-18T15:45:59.303Z","etag":null,"topics":["ainsleydev","golang","platform","terraform","webkit"],"latest_commit_sha":null,"homepage":null,"language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ainsleydev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2025-11-17T19:18:06.000Z","updated_at":"2025-11-18T14:48:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ainsleydev/platform","commit_stats":null,"previous_names":["ainsleydev/platform"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ainsleydev/platform","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainsleydev%2Fplatform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainsleydev%2Fplatform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainsleydev%2Fplatform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainsleydev%2Fplatform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ainsleydev","download_url":"https://codeload.github.com/ainsleydev/platform/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ainsleydev%2Fplatform/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31895650,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T11:36:10.202Z","status":"ssl_error","status_checked_at":"2026-04-16T11:36:09.652Z","response_time":69,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["ainsleydev","golang","platform","terraform","webkit"],"created_at":"2026-04-16T17:02:02.730Z","updated_at":"2026-04-16T17:02:04.091Z","avatar_url":"https://github.com/ainsleydev.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ainsley.dev Platform\n\nInfrastructure as Code for platform services (monitoring, observability, etc.) using Terraform and\nAnsible.\n\n## Overview\n\nThis repository manages infrastructure for:\n\n- **Peekaping**: Monitoring service\n- **Backups**: Terraform backups from Backblaze to Google Drive.\n\n## Architecture\n\n- **Infrastructure**: Terraform with Hetzner Cloud\n- **Configuration**: Ansible (references roles from [WebKit](https://github.com/ainsleydev/webkit))\n- **Deployment**: Docker Compose on VMs\n- **State**: Backblaze B2 remote backend\n\n## Directory Structure\n\n```\nplatform/\n├── terraform/\n│   ├── base/                     # Base Terraform configuration\n│   │   ├── providers.tf          # Hetzner provider\n│   │   ├── backend.tf            # B2 remote state\n│   │   ├── variables.tf          # Global variables\n│   │   ├── outputs.tf            # Global outputs\n│   │   └── main.tf               # Module imports\n│   └── services/\n│       └── peekaping/            # Peekaping monitoring service\n├── ansible/\n│   ├── playbooks/\n│   │   └── peekaping.yaml        # Peekaping deployment\n│   └── ansible.cfg               # References WebKit roles\n├── docker/\n│   └── peekaping/\n│       ├── docker-compose.yml\n│       └── .env.example\n```\n\n## Setup\n\n### 1. Configure Terraform Variables\n\n```bash\n# Copy example tfvars\ncp terraform.tfvars.example terraform.tfvars\n\n# Edit with your Hetzner token and other values\nvim terraform.tfvars\n```\n\n### 2. Initialize Terraform\n\n```bash\n# Initialize with B2 backend\nmake init\n\n# Or manually:\n# cd terraform/base\n# terraform init \\\n#   -backend-config=\"access_key=${BACK_BLAZE_KEY_ID}\" \\\n#   -backend-config=\"secret_key=${BACK_BLAZE_APPLICATION_KEY}\"\n```\n\n## CI/CD Automation\n\nThis repository uses automated Terraform workflows for infrastructure changes:\n\n### Workflow Overview\n\n1. **Pull Request** - Terraform plan runs automatically\n   - Shows what infrastructure changes will be made\n   - Posts plan output as PR comment\n   - Detects destructive changes (deletions) and warns\n   - Validates Terraform syntax and security (tfsec, Checkov)\n   - Saves plan artifact for exact apply on merge\n\n2. **Merge to Main** - Terraform apply runs with approval gate\n   - Downloads saved plan from PR (ensures plan-apply match)\n   - Requires approval on `production` environment before applying\n   - Backs up state before making changes\n   - Posts results back to merged PR and commit\n   - Only runs if Terraform files changed\n\n### Reusable Workflows\n\nThe repository includes reusable workflow helpers:\n\n- **`.github/workflows/helper-plan.yaml`** - Reusable plan workflow\n  - Runs terraform plan\n  - Posts formatted results to PR\n  - Uploads plan artifact\n  - Detects destructive changes\n\n- **`.github/workflows/helper-apply.yaml`** - Reusable apply workflow\n  - Downloads plan artifact from PR\n  - Backs up state before apply\n  - Applies infrastructure changes\n  - Requires GitHub environment approval\n\n### Secrets Configuration\n\nWorkflows use GitHub organization secrets (already configured):\n\n- `ORG_HETZNER_TOKEN` - Hetzner Cloud API token\n- `ORG_BACK_BLAZE_KEY_ID` - Backblaze B2 access key for state backend\n- `ORG_BACK_BLAZE_APPLICATION_KEY` - Backblaze B2 secret key\n\n### GitHub Environment Setup\n\nThe `production` environment must be configured with:\n\n1. Go to **Settings → Environments → New environment**\n2. Name: `production`\n3. Add protection rules:\n   - ✅ Required reviewers (select yourself)\n   - ✅ Deployment branches: `main` only\n   - Optional: Wait timer (0-30 minutes)\n\n### Making Infrastructure Changes\n\n#### Automated (Recommended)\n\n```bash\n# 1. Create a feature branch\ngit checkout -b feat/add-new-service\n\n# 2. Make your Terraform changes\nvim terraform/services/new-service/main.tf\n\n# 3. Push and create PR\ngit push origin feat/add-new-service\ngh pr create --title \"Add new service\"\n\n# 4. Review plan output in PR comment\n# 5. Get PR approval, then merge\n# 6. Approve the deploy in GitHub Actions (production environment)\n# 7. Changes applied automatically!\n```\n\n#### Manual (Emergency/Testing)\n\n```bash\n# Plan deployment\nmake plan\n\n# Apply (creates VM, volume, firewall)\nmake apply\n\n# Get access details\nmake output\n```\n\n### Emergency Procedures\n\nIf the automated workflow fails:\n\n1. **Check the workflow logs**: Actions tab → Failed workflow → View logs\n2. **Manual apply via workflow_dispatch**: Actions → Terraform Apply → Run workflow\n3. **Local manual apply**: Use `make apply` with local credentials\n4. **State recovery**: Download backup from workflow artifacts (retained 90 days)\n\n## Ansible Roles\n\nThis project references Ansible roles from the [WebKit](https://github.com/ainsleydev/webkit)\nrepository:\n\n- `docker` - Docker installation\n- `nginx` - Nginx web server with SSL\n- `certbot` - Let's Encrypt SSL certificates\n- `ufw` - Firewall configuration\n- `fail2ban` - Intrusion prevention\n\nSee `ansible/ansible.cfg` for role path configuration.\n\n## Terraform Modules\n\nThis project adapts patterns\nfrom [WebKit's Terraform modules](https://github.com/ainsleydev/webkit/tree/main/platform/terraform):\n\n- Hetzner server provisioning\n- Firewall rules\n- SSH key generation\n- Cloud-init integration\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fainsleydev%2Fplatform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fainsleydev%2Fplatform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fainsleydev%2Fplatform/lists"}