{"id":16164024,"url":"https://github.com/cyclenerd/google-cloud-server-on-demand","last_synced_at":"2025-10-12T07:38:53.087Z","repository":{"id":72096155,"uuid":"574635434","full_name":"Cyclenerd/google-cloud-server-on-demand","owner":"Cyclenerd","description":"▶️ Server on Demand Appliance (Google Compute Engine) - Cloud Build with Terraform and Ansible Showcase","archived":false,"fork":false,"pushed_at":"2025-06-17T14:03:28.000Z","size":4219,"stargazers_count":13,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-17T15:23:28.454Z","etag":null,"topics":["ansible","automation","google-cloud-build","google-cloud-platform","google-compute-engine","internet-of-things","iot","linux","python","raspberry-pi","terraform"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cyclenerd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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}},"created_at":"2022-12-05T18:38:46.000Z","updated_at":"2025-06-17T14:03:29.000Z","dependencies_parsed_at":"2023-10-16T11:22:25.002Z","dependency_job_id":"998b46ef-b800-4a40-9f78-f046aa6df0bd","html_url":"https://github.com/Cyclenerd/google-cloud-server-on-demand","commit_stats":null,"previous_names":["cyclenerd/google-cloud-server-on-demand"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Cyclenerd/google-cloud-server-on-demand","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cyclenerd%2Fgoogle-cloud-server-on-demand","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cyclenerd%2Fgoogle-cloud-server-on-demand/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cyclenerd%2Fgoogle-cloud-server-on-demand/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cyclenerd%2Fgoogle-cloud-server-on-demand/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cyclenerd","download_url":"https://codeload.github.com/Cyclenerd/google-cloud-server-on-demand/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cyclenerd%2Fgoogle-cloud-server-on-demand/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260733660,"owners_count":23054308,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["ansible","automation","google-cloud-build","google-cloud-platform","google-compute-engine","internet-of-things","iot","linux","python","raspberry-pi","terraform"],"created_at":"2024-10-10T02:44:59.818Z","updated_at":"2025-10-12T07:38:53.079Z","avatar_url":"https://github.com/Cyclenerd.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Server on Demand Appliance (Google Compute Engine)\n\n**Get your own Google Compute Engine virtual machine (VM) with the simple push of a button.**\n\n![Image: Server on Demand Appliance at DIGITAL X 2023](./img/soda-gce-digitalx-2023.jpg)\n\nThis project is intended to show how quickly and easily virtual machines can be configured and set up using Google Cloud and Infrastructure as Code (IaC) tools.\nYou have the choice between four Linux based operating systems.\nYou trigger a continuous integration / continuous deployment (CI/CD) pipeline by pressing a button.\nA virtual machine is then provisioned and installed for you in the Google Cloud.\nIn the background, [Google Cloud Build](https://cloud.google.com/build) uses [Terraform](https://www.terraform.io/) and [Ansible](https://www.ansible.com/) to build your own VM.\nYou will get your own user login data printed on a receipt and you can log in via SSH after a few minutes.\n\n![Image: Terraform and Ansible](./img/terraform_ansible_logo.jpg)\n\nThis project also shows you how well the Google Cloud can scale.\nTested with over 150 VMs. [700 VMs](./QUOTA.md) is the default limit.\n\n## 🤔 Why\n\nI saw the Shells on Demand Appliance \"SODA\" from National Upcycled Computing Collective (NUCC) at the DEF CON 30 conference in Las Vegas. Unfortunately not in person but in this [YouTube video](https://www.youtube.com/watch?v=e69zcwISo3Y).\n\nTL;DR: It's a vending machine. You pay, press a button and get your own virtual machine (VM).\n\n![Image: Shells on Demand Appliance at DEF CON 30](./img/soda-las_vegas.jpg)\n\n*Image Source: [@strangepartscom](https://twitter.com/strangepartscom/status/1558566808205987840/), [@Zhoratrope](https://twitter.com/Zhoratrope/status/1558160122957799424)*\n\nI was quite impressed and excited by the idea. I wanted something like this too. Unfortunately, I don't have enough space and I don't even have a real vending machine either.\n\nThanks to Google and the Internet, the hardware does not have to be physically located in a vending machine. The hardware can be located in one of the many [Google Cloud data centers](https://gcloud-compute.com/regions.html). This saves a lot of space and you only need the buttons and a thermal receipt printer to have a similar setup to the SODA vending machine. That's exactly what I did with this project.\n\n## 🚀 Technology\n\n![Badge: Google Cloud](https://img.shields.io/badge/Google%20Cloud-%234285F4.svg?logo=google-cloud\u0026logoColor=white)\n![Badge: Terraform](https://img.shields.io/badge/Terraform-%235835CC.svg?logo=terraform\u0026logoColor=white)\n![Badge: Packer](https://img.shields.io/badge/Packer-02A8EF.svg?logo=packer\u0026logoColor=white)\n![Badge: Ansible](https://img.shields.io/badge/Ansible-%231A1918.svg?logo=ansible\u0026logoColor=white)\n![Badge: Raspberry Pi](https://img.shields.io/badge/Raspberry%20Pi-C51A4A?logo=Raspberry-Pi)\n\n\u003e [!CAUTION]\n\u003e **Killed by Google:** Starting June 17, 2024, the Google Cloud Service \"[Cloud Source Repositories](https://cloud.google.com/source-repositories)\" required for this project will no longer be accessible to new customers.\n\u003e If your organization hasn't previously used Cloud Source Repositories, you can't enable the API or use Cloud Source Repositories.\n\u003e New projects not connected to an organization can't enable the Cloud Source Repositories API.\n\u003e Organizations that have used Cloud Source Repositories prior to June 17, 2024 are not affected by this change. \n\nThe following technologies are used:\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eGoogle Cloud Platform\u003c/b\u003e\u003c/summary\u003e\n\n- [x] [Compute Engine](https://cloud.google.com/compute)\n- [x] [Operating system images](https://cloud.google.com/compute/docs/images/os-details)\n\t- [x] [Debian GNU/Linux](https://en.wikipedia.org/wiki/Debian)\n\t- [x] [Ubuntu LTS](https://en.wikipedia.org/wiki/Ubuntu)\n\t- [x] [Fedora Linux](https://en.wikipedia.org/wiki/Fedora_Linux)\n\t- [x] [openSUSE](https://en.wikipedia.org/wiki/OpenSUSE)\n- [x] [Cloud Storage](https://cloud.google.com/storage)\n- [x] [Cloud Source Repositories](https://cloud.google.com/source-repositories)\n- [x] [Cloud Pub/Sub](https://cloud.google.com/pubsub)\n- [x] [Cloud Build](https://cloud.google.com/build)\n\t- [x] [Docker Container image](https://github.com/Cyclenerd/cloud-tools-container#readme)\n- [x] [Cloud Function](https://cloud.google.com/functions)\n- [x] [Artifact Registry](https://cloud.google.com/artifact-registry)\n- [x] [Cloud DNS](https://cloud.google.com/dns)\n- [x] [Cloud Firewall](https://cloud.google.com/firewalls)\n- [x] [Cloud Logging and Monitoring](https://cloud.google.com/monitoring)\n- [x] [Cloud Scheduler](https://cloud.google.com/scheduler)\n- [x] [Identity and Access Management (IAM)](https://cloud.google.com/iam)\n- [x] [Resource Manager](https://cloud.google.com/resource-manager)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eTerraform\u003c/b\u003e\u003c/summary\u003e\n\n- [x] [Google provider](https://registry.terraform.io/providers/hashicorp/google/)\n- [x] [Archive provider](https://registry.terraform.io/providers/hashicorp/archive/)\n- [x] [Local provider](https://registry.terraform.io/providers/hashicorp/local/)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003ePacker\u003c/b\u003e\u003c/summary\u003e\n\n- [x] [Google Cloud Platform](https://developer.hashicorp.com/packer/integrations/hashicorp/googlecompute)\n- [x] [Ansible](https://developer.hashicorp.com/packer/integrations/hashicorp/ansible)\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eAnsible\u003c/b\u003e\u003c/summary\u003e\n\n- [x] apt\n- [x] command\n- [x] copy\n- [x] dnf\n- [x] file\n- [x] get_url\n- [x] git\n- [x] uri\n- [x] user\n- [x] zypper\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eRaspberry Pi\u003c/b\u003e\u003c/summary\u003e\n\n- [x] [Raspberry Pi OS](https://www.raspberrypi.com/software/operating-systems/)\n- [x] [Python 3](https://www.python.org/)\n\u003c/details\u003e\n\n\nAll components put together correctly result in the Server on Demand Appliance Google Cloud version.\n\n## 🪄 Process of creating a VM\n\n![Badge: Fedora](https://img.shields.io/badge/Fedora-51A2DA.svg?logo=fedora\u0026logoColor=white)\n![Badge: Ubuntu](https://img.shields.io/badge/Ubuntu-E95420.svg?logo=ubuntu\u0026logoColor=white)\n![Badge: Debian](https://img.shields.io/badge/Debian-A81D33.svg?logo=debian\u0026logoColor=white)\n![Badge: openSUSE](https://img.shields.io/badge/openSUSE-73BA25.svg?logo=opensuse\u0026logoColor=white)\n\nhttps://user-images.githubusercontent.com/176242/205736692-b19bca68-a94c-4e95-8c32-79a9f7dfc7a9.mp4\n\n[📺 YouTube Video](https://www.youtube.com/watch?v=9a_9sfi7aaU)\n\nIn order to create a VM, many steps are carried out.\nEverything goes very fast.\nWhile the user is already holding his paper with login information,\nfurther steps are executed in the cloud.\n\n[![Drawing: SODA Google Compute Engine version](./img/soda-gcp.png)](./img/soda-gcp.png)\n\n**Raspberry Pi:**\n\n1. User presses one of the four buttons\n\t* 🔵 Blue : Fedora Linux\n\t* 🟡 Yellow : Ubuntu LTS\n\t* 🔴 Red : Debian GNU/Linux\n\t* 🟢 Green : openSUSE\n2. Message is published to Cloud Pub/Sub topic\n3. Paper receipt with login information is printed\n\n**Google Cloud Platform:**\n\n3. Pub/Sub triggers Cloud Build\n4. A Cloud Build job is started\n\t1. Cloud Build downloads [Docker container image](https://github.com/Cyclenerd/cloud-tools-container) with tools (Google Cloud CLI, Terraform, Ansible)\n\t1. Required scripts are loaded from the Cloud Source Repository\n\t\t* Effective June 17, 2024, Cloud Source Repositories isn't available to new customers!\n\t\t* If your organization hasn't previously used Cloud Source Repositories, you can't enable the API or use Cloud Source Repositories.\n\t1. Pub/Sub message is read and evaluated\n5. Terraform creates the infrastructure\n\t* Static public IP is registered\n\t* DNS entry is created\n\t* VM with disk and operating system is created\n\t* Custom OS image is used\n\t* Cloud Scheduler to destroy infrastructure is scheduled\n\t* Terraform state is stored in a Google Cloud Storage bucket\n6. Ansible takes care of configuring the operating system\n\t* Set up user (username and password)\n\n### Machine configuration\n\nThe following configuration is used by default:\n\n* Machine type: [`e2-micro`](https://gcloud-compute.com/e2-micro.html)\n\t* vCPU: 2 shared Intel (x86/64)\n\t* Memory: 1 GB\n* Disk:\n\t* Type: [Balanced persistent disk](https://cloud.google.com/compute/docs/disks#disk-types) (SSD)\n\t* Size: 25 GB\n* External IP address: Premium\n* Region: [`europe-west1`](https://gcloud-compute.com/europe-west1/e2-micro.html) (Belgium) \n\n**Costs:**\n\nEstimated cost per `e2-micro` VM, without guarantee:\n\n|                  | $ 1h     | $ 3h   |\n|------------------|----------|--------|\n| CPU and memory   | `0.0092` | `0.03` |\n| Disk (25GB)¹     | `0.0034` | `0.01` |\n| Static public IP | `0.0034` | `0.01` |\n| **Total**        | `0.0160` | `0.05` |\n\n¹ Balanced persistent disk: 0.1 USD per 1 GB and month,\n25 GB per month = 2.50 USD,\none month = 730 hours,\n2.50 USD / 730h = 0.0034 USD,\n0.0034 USD * 3h = 0.010 USD for 25 GB for 3h\n\nThere are other small costs for:\n\n* Cloud Build build time\n* Source Repository users\n* Cloud Scheduler jobs\n* Cloud DNS managed zone\n* Network Internet egress traffic\n\nSource: [Google Cloud Pricing Calculator](https://cloud.google.com/products/calculator/#id=7b564b38-e2c4-43bc-8e50-9a21b71d0c48)\n\n## 🚀 Setup\n\n### 1. Clone\n\nClone this repository:\n\n```bash\ngit clone https://github.com/Cyclenerd/google-cloud-shells-on-demand.git\ncd google-cloud-shells-on-demand\n```\n### 2. Google Cloud Platform\n\nPlease follow the instructions in the folder [gcp](./gcp/README.md).\n\n```bash\ncd gcp\n```\n\n### 3. Raspberry Pi\n\nPlease follow the instructions in the folder [pi](./pi/README.md).\n\n```bash\ncd pi\n```\n\n## 🔦 Further functions\n\nIn addition to creating the infrastructure, there are a few other functions.\n\n### Automatic expiration\n\nAfter a defined time (default 3 hours), your VM and its entire infrastructure will be deleted.\n\n![Image: Cloud Scheduler](./img/destroy.png)\n\nThis is triggered by a Cloud Scheduler set up during the creation of the VM.\nA Cloud Build job then takes care of the destruction of the VM and its infrastructure.\nThis works because an extra separate Terraform state is saved for each VM.\n\nYou can adjust the expiration time (minutes) in `terraform.tfvars` in the `gcp` directory.\n\n```text\n# Expires in minutes\nexpires = \"180\"\n```\n\n### Back on\n\nAfter logging in to your VM via SSH, you can become root.\nThen you can do anything, even shut down the VM:\n\n```bash\nsudo poweroff\n```\n\n![Image: Cloud Build](./img/on-again.png)\n\nIf you do this, a event will be saved in the Google Cloud audit log and a new Cloud Build job will be triggered.\n\nThis Cloud Build job then starts your VM again. Feel free to test it 😊.\n\n### Cloud Build notifications\n\nGet notified via [Discord](https://discord.com/) and/or [Pushover](https://pushover.net/) when a Cloud Build job is failed (`ERROR`) or timed out (`TIMEOUT`).\n\n#### Discord\n\nGet notified via [Discord](https://discord.com/):\n\n![Image: Discord](./img/cloudbuild-discord.png)\n\n1. Create an Discord webhook URL for your Discord channel: \u003chttps://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks\u003e\n\t\n\tThe webhook URL should look similar to the following:\n\n\t```text\n\thttps://discord.com/api/webhooks/[WEBHOOK-ID]/[WEBHOOK-TOKEN]\n\t```\n\n1. Add the Discord webhook URL to `terraform.tfvars` in `gcp` directory:\n\t\n\t```text\n\tdiscord-webhook-url = \"https://discord.com/api/webhooks/[WEBHOOK-ID]/[WEBHOOK-TOKEN]\"\n\t```\n\n1. Deploy Cloud Function\n\t\n\t```bash\n\tterraform apply\n\t```\n\nYou can test the notification with the manual Cloud Build trigger `simulate-error`.\n\n#### Pushover\n\nGet notified via [Pushover](https://pushover.net/):\n\n![Image: Pushover](./img/cloudbuild-pushover.png)\n\n1. Register your application, set its name and upload an icon, and get an API token in return: \u003chttps://pushover.net/apps/build\u003e\n\n\tExample icon:\n\n\t![Image: Pushover icon](./img/button-icon-72x72.png)\n\n\t*MazeNL77, [CC BY 3.0](https://creativecommons.org/licenses/by/3.0), via [Wikimedia Commons](https://commons.wikimedia.org/wiki/File:Perspective-Button-Stop-icon.png)*\n\n\n1. Add your Pushover user/group key (not e-mail address) and the application's API token/key to `terraform.tfvars` in `gcp` directory:\n\t\n\t```text\n\tpushover-user-key = \"[PUSHOVER-USER-KEY]\"\n\tpushover-api-token = \"[PUSHOVER-API-TOKEN]\"\n\t```\n\n1. Deploy Cloud Function\n\t\n\t```bash\n\tterraform apply\n\t```\n\nYou can test the notification with the manual Cloud Build trigger `simulate-error`.\n\n### Raspberry Pi CPU temp. monitoring\n\nThe CPU of the Raspberry Pi can get hot in the wooden box.\nFor safety and documentation, the CPU temperature is logged and can be monitored.\n\n![Image: CPU temp. monitoring](./img/temp-monitoring.png)\n\n\n### Monitoring dashboards\n\nTwo custom monitoring dashboards are set up:\n\n#### Raspberry Pi\n\n![Image: Raspberry Pi monitoring dashbaord](./img/monitoring-dashboard-raspi.png)\n\n#### VMs\n\n![Image: VMs monitoring dashbaord](./img/monitoring-dashboard-vms.png)\n\n### Artifact Registry repository\n\nYou can use the Artifact Registry as a location for the Docker container image.\nThe image then does not have to be downloaded from Docker Hub during the Cloud Build jobs.\n\n![Image: Copy container](./img/copy-image.png)\n\n1. Copy the image by running the manual trigger `copy-image`.\n1. Replace `cyclenerd/cloud-tools-container:latest` with `[LOCATION]-docker.pkg.dev/[PROJECT_ID]/cointainer/cloud-tools-container:latest` in the Cloud Build YAML files (i.e. [`create.yml`](./cloudbuild/create.yml)) in folder the [cloudbuild](./cloudbuild/).\n1. Push changes to Cloud Source repository:\n\n\t```bash\n\tgit push cloudsource\n\t```\n\n\n## ❤️ Contributing\n\nHave a patch that will benefit this project?\nAwesome! Follow these steps to have it accepted.\n\n1. Please read [how to contribute](CONTRIBUTING.md).\n1. Fork this Git repository and make your changes.\n1. Create a Pull Request.\n1. Incorporate review feedback to your changes.\n1. Accepted!\n\n\n## 📜 License\n\nAll files in this repository are under the [Apache License, Version 2.0](LICENSE) unless noted otherwise.\n\nPlease note:\n\n* No warranty\n* No official Google product","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyclenerd%2Fgoogle-cloud-server-on-demand","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcyclenerd%2Fgoogle-cloud-server-on-demand","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyclenerd%2Fgoogle-cloud-server-on-demand/lists"}