{"id":51045603,"url":"https://github.com/stackitcloud/stackit-cmf-rehost-springboot","last_synced_at":"2026-06-22T13:32:23.786Z","repository":{"id":356102657,"uuid":"1230809420","full_name":"stackitcloud/stackit-cmf-rehost-springboot","owner":"stackitcloud","description":"STACKIT Cloud Framework Rehost Springboot Example","archived":false,"fork":false,"pushed_at":"2026-05-06T15:56:31.000Z","size":52880,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-06T17:34:57.149Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stackitcloud.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":"2026-05-06T10:44:20.000Z","updated_at":"2026-05-06T15:57:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/stackitcloud/stackit-cmf-rehost-springboot","commit_stats":null,"previous_names":["stackitcloud/stackit-cmf-rehost-springboot"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/stackitcloud/stackit-cmf-rehost-springboot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cmf-rehost-springboot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cmf-rehost-springboot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cmf-rehost-springboot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cmf-rehost-springboot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stackitcloud","download_url":"https://codeload.github.com/stackitcloud/stackit-cmf-rehost-springboot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stackitcloud%2Fstackit-cmf-rehost-springboot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34651748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2026-06-22T13:32:22.851Z","updated_at":"2026-06-22T13:32:23.770Z","avatar_url":"https://github.com/stackitcloud.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stackit-cmf-rehost-springboot\n\nRunnable Rehost automation example for STACKIT using Terraform and Ansible.\n\n## What this repo does\n\n- Provisions network/security and a VM in STACKIT via Terraform.\n- Assigns a public IP and SSH key.\n- Bridges to Ansible to install Java, copy a Spring Boot JAR, and run it as a `systemd` service.\n- Optionally provisions STACKIT Observability, registers scrape jobs, and imports a starter Grafana dashboard.\n\nThe repository includes a ready-to-deploy sample Spring Boot artifact at `ansible/files/springboot-app.jar`.\nBy default, Terraform/Ansible deploy this artifact via `jar_local_path = \"ansible/files/springboot-app.jar\"`.\n\nThe example can also install a VM-local PostgreSQL and wire Spring Boot to that database when\n`enable_local_postgresql = true`.\n\n## Prerequisites\n\n- Terraform `\u003e= 1.5`\n- Ansible\n- SSH key pair available on your machine (default: `~/.ssh/id_rsa` and `~/.ssh/id_rsa.pub`)\n- A STACKIT service account email (used as project owner in `target_project_owner_email`)\n- Downloaded JSON key file for this service account (referenced via `service_account_key_path`)\n- Permissions for the service account on folder or organization scope so project/network/compute resources can be created\n- Parent container ID where the project should be created (`parent_container_id`)\n\nAuthentication for this example is based on the service account JSON key file.\n`STACKIT_SERVICE_ACCOUNT_TOKEN` is not required.\n\n## Quick start\n\n1. Copy the example variables file:\n\n```bash\ncp env.tfvars.example env.tfvars\n```\n\n2. Edit `env.tfvars` and set at least:\n\n- `service_account_key_path`\n- `target_project_owner_email`\n- `parent_container_id`\n\n`bootstrap_project_id` can stay as placeholder when `parent_container_id` is set.\n\n3. Initialize and run Terraform:\n\n```bash\nterraform init\nterraform plan -var-file=env.tfvars\nterraform apply -var-file=env.tfvars\n```\n\nTo enable observability rollout in the same apply, set these values in `env.tfvars`:\n\n- `enable_observability = true`\n- `enable_node_exporter = true`\n- `create_grafana_dashboard = true`\n\nOptional (only if your app exposes Prometheus metrics):\n\n- `enable_springboot_metrics_scrape = true`\n- `springboot_metrics_path = \"/actuator/prometheus\"`\n\nOptional (to generate local demo traffic directly from the VM):\n\n- `enable_local_load_generator = true`\n\nOptional (to enable VM-local PostgreSQL for the app):\n\n- `enable_local_postgresql = true`\n- `postgresql_db_name = \"springmusic\"`\n- `postgresql_app_username = \"springmusic\"`\n- `postgresql_app_password = \"...\"`\n\nOptional (to import source data during provisioning):\n\n- `postgresql_source_dump_local_path = \"/absolute/path/to/source.dump\"`\n- `postgresql_restore_after_copy = true`\n\n## Common flag wrapper\n\nTo use the common CMF flags, copy and adjust:\n\n```bash\ncp flags.env.example flags.env\n```\n\nThen run:\n\n```bash\n./scripts/apply_with_common_flags.sh flags.env env.tfvars\n```\n\nCommon flags:\n\n- `setup_project`\n- `setup_observability`\n- `setup_database`\n- `setup_workload`\n- `setup_loadgen`\n- `setup_dns`\n\n4. After apply:\n\n```bash\nterraform output vm_public_ip\nterraform output application_url\nterraform output observability_grafana_url\n```\n\n## Observability behavior\n\n- When `enable_observability = true`, Terraform creates a STACKIT Observability instance.\n- Ansible installs `prometheus-node-exporter` on the VM and writes custom app health metrics (`springboot_up`, `springboot_http_status_code`) via the textfile collector.\n- If `enable_local_load_generator = true`, Ansible also writes request counter metrics (`springboot_http_requests_total`) via the same textfile collector.\n- Terraform creates a scrape job for node exporter (`:9100/metrics`).\n- Optionally, Terraform also creates a scrape job for `springboot_metrics_path`.\n- If `create_grafana_dashboard = true`, Terraform imports `dashboards/rehost-observability-dashboard.json` into Grafana.\n- If `enable_local_load_generator = true`, Ansible installs a local load generator (`springboot-loadgen.service` + `springboot-loadgen.timer`) that calls the app endpoint with an irregular burst profile.\n\n### Grafana dashboard snapshot\n\n![Grafana dashboard snapshot for rehost spring boot observability](assets/images/scf_rehost_spring_boot_grafana.png)\n\n### Local irregular load profile\n\nYou can tune the generated load in `env.tfvars`:\n\n- `springboot_loadgen_target_path` (default: `/`)\n- `springboot_loadgen_base_interval_seconds` (default: `8`)\n- `springboot_loadgen_randomized_delay_seconds` (default: `8`)\n- `springboot_loadgen_burst_min_requests` (default: `40`)\n- `springboot_loadgen_burst_max_requests` (default: `160`)\n- `springboot_loadgen_enable_stress` (default: `true`)\n- `springboot_loadgen_stress_cpu_workers` (default: `2`)\n- `springboot_loadgen_stress_vm_workers` (default: `1`)\n- `springboot_loadgen_stress_vm_bytes` (default: `40%`)\n- `springboot_loadgen_stress_timeout_seconds` (default: `15`)\n\nThe timer uses `OnUnitActiveSec` + `RandomizedDelaySec`, and each run sends a random number of requests with short random pauses between requests.\nIf `springboot_loadgen_enable_stress = true`, each run additionally executes `stress-ng` to generate CPU and RAM pressure.\n\nRequest-related exported metrics from the load generator:\n\n- `springboot_http_requests_total`\n- `springboot_http_requests_last_burst`\n- `springboot_http_requests_last_burst_success`\n- `springboot_http_requests_last_burst_failed`\n- `springboot_loadgen_stress_enabled`\n- `springboot_loadgen_stress_applied`\n- `springboot_loadgen_stress_cpu_workers`\n- `springboot_loadgen_stress_vm_workers`\n- `springboot_loadgen_stress_timeout_seconds`\n\nThe default dashboard includes `Spring Boot HTTP Requests (5m)` based on:\n\n`sum by (instance) (increase(springboot_http_requests_total[5m]))`\n\nSecurity note: with `expose_node_exporter_port = true`, port `9100` is exposed via the security group. Restrict this according to your network policy.\n\n## Spring Boot artifact used for deployment\n\n- Default artifact path: `ansible/files/springboot-app.jar`\n- To deploy a different app, replace this file or set `jar_local_path` in `env.tfvars`.\n\n## Rehost data migration path (source PostgreSQL -\u003e target VM PostgreSQL)\n\nUse this flow when `enable_local_postgresql = true`.\n\n1. On the source system, export data:\n\n```bash\npg_dump --format=custom --no-owner --no-privileges --dbname=\u003csource-db\u003e --file=/tmp/source.dump\n```\n\n2. Copy the dump file to your Terraform execution host.\n3. Set in `env.tfvars`:\n\n```hcl\nenable_local_postgresql           = true\npostgresql_source_dump_local_path = \"/tmp/source.dump\"\npostgresql_restore_after_copy     = true\n```\n\n4. Run `terraform apply -var-file=env.tfvars`.\n\nAnsible copies the dump to the target VM and restores it with `pg_restore` into `postgresql_db_name`.\n\n## Destroy\n\n```bash\nterraform destroy -var-file=env.tfvars\n```\n\n## Notes\n\n- `env.tfvars.example` contains placeholders by design. Fill them in `env.tfvars` before running.\n- If your region uses a different image/flavor, adjust `image_id` and `machine_type`.\n- `ansible` is triggered automatically by Terraform via `terraform_data`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackitcloud%2Fstackit-cmf-rehost-springboot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstackitcloud%2Fstackit-cmf-rehost-springboot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstackitcloud%2Fstackit-cmf-rehost-springboot/lists"}