This Terraform module provisions a Google Compute Engine virtual machine with SSH access for use with Instruqt custom resources. It automatically generates SSH key pairs and configures the VM for immediate access.
- Compute Instance: An e2-micro VM running Debian 11
- SSH Key Pair: Automatically generated RSA 4096-bit key pair
- Public IP: External IP address for accessing the VM
- SSH Access: Pre-configured SSH access with the generated key
- A Google Cloud project with billing enabled
- Compute Engine API enabled
- Service account credentials with permissions to:
- Create compute instances
- Manage instance metadata
To use this module as a custom resource in Instruqt, follow these steps:
First, publish this module to the Terraform Registry:
- Ensure your module follows Terraform's standard module structure
- Tag a release in your GitHub repository (e.g.,
v1.0.0) - The module will be automatically published to the registry if your repository is public and properly configured
- Navigate to your Instruqt organization settings
- Go to the Custom Resources section
- Click Import from Terraform Registry
- Search for and select your published module
- Configure the module with any organization-wide defaults
Once imported, you can add the custom resource to your track through the Instruqt UI:
- Open your track in the Instruqt editor
- Navigate to the Sandbox configuration
- Click Add Resource
- Select your imported custom resource
- Configure the required inputs:
credentials: Your GCP service account credentials (use secrets)project: Your GCP project IDname: VM name (e.g., "student-vm")sandbox_id: Use the${SANDBOX_ID}variableregion: GCP region (optional, defaults to "europe-west1")zone: GCP zone (optional, defaults to "europe-west1-b")ssh_username: SSH username (optional, defaults to "instruqt")
| Variable | Description |
|---|---|
credentials |
JSON credentials for authenticating with GCP |
project |
The Google Cloud project ID |
name |
Name of the virtual machine (will be prefixed with sandbox_id) |
sandbox_id |
Unique identifier for the Instruqt sandbox |
| Variable | Default | Description |
|---|---|---|
region |
"europe-west1" |
The region to deploy the VM |
zone |
"europe-west1-b" |
The zone to deploy the VM |
ssh_username |
"instruqt" |
Username for SSH access to the VM |
The following outputs are available for use in your Instruqt track:
| Output | Description | Sensitive |
|---|---|---|
id |
The self-link of the VM instance | No |
external_ip |
External IP address of the VM | No |
ssh_private_key |
Private SSH key in OpenSSH format | Yes |
ssh_public_key |
Public SSH key in OpenSSH format | No |
ssh_username |
Username for SSH access | No |
ssh_command |
Ready-to-use SSH command | No |
The module automatically generates SSH keys and configures the VM. Use these outputs in your track's lifecycle scripts or challenge scripts:
# Create SSH directory if it doesn't exist
mkdir -p /root/.ssh
# Save the private key
echo "${GCP_VM_SSH_PRIVATE_KEY}" > /root/.ssh/gcp_vm_key
chmod 600 /root/.ssh/gcp_vm_key# Method 1: Use the generated SSH command (copy the key first)
ssh -i /root/.ssh/gcp_vm_key -o StrictHostKeyChecking=no \
${GCP_VM_SSH_USERNAME}@${GCP_VM_EXTERNAL_IP}
# Method 2: Using gcloud (if available)
gcloud compute ssh ${GCP_VM_SSH_USERNAME}@<vm-name> \
--zone=${zone} \
--ssh-key-file=/root/.ssh/gcp_vm_key#!/bin/bash
# Save this as a setup script for your Instruqt challenge
# Configure SSH key
mkdir -p /root/.ssh
echo "${GCP_VM_SSH_PRIVATE_KEY}" > /root/.ssh/gcp_vm_key
chmod 600 /root/.ssh/gcp_vm_key
# Test SSH connection
ssh -i /root/.ssh/gcp_vm_key \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
${GCP_VM_SSH_USERNAME}@${GCP_VM_EXTERNAL_IP} \
"echo 'SSH connection successful!'"
# Create SSH config for easier access
cat > /root/.ssh/config <<EOF
Host gcp-vm
HostName ${GCP_VM_EXTERNAL_IP}
User ${GCP_VM_SSH_USERNAME}
IdentityFile /root/.ssh/gcp_vm_key
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
EOF
# Now you can simply use: ssh gcp-vmThe module creates a VM with the following specifications:
- Machine Type: e2-micro (2 vCPUs, 1 GB memory)
- Operating System: Debian 11
- Network: Default VPC with external IP
- Disk: Standard persistent disk (default size)
To customize the VM, you can modify main.tf to expose additional variables for machine type, image, or disk configuration.
VMs are created with the following naming format:
{sandbox_id}-{name}
Example: abc123def-student-vm
This ensures unique instance names and easy identification of sandbox resources.
- SSH keys are automatically generated for each sandbox
- Private keys are marked as sensitive in Terraform outputs
- Public keys are stored in VM metadata
- External IP is exposed for direct SSH access
- Consider adding firewall rules if additional network security is needed
- VMs are automatically destroyed when the sandbox ends
When configuring this custom resource in the Instruqt UI, here are example values you might use:
| Input | Example Value |
|---|---|
credentials |
${GOOGLE_CREDENTIALS} (secret variable) |
project |
my-gcp-project |
name |
linux-server |
sandbox_id |
${SANDBOX_ID} (Instruqt variable) |
region |
us-central1 |
zone |
us-central1-a |
ssh_username |
student |
To provision multiple VMs, add the custom resource multiple times in the Instruqt UI with different names:
- Add the custom resource once and name it "web-server"
- Set
nameinput to "web"
- Set
- Add the custom resource again and name it "database-server"
- Set
nameinput to "db"
- Set
Each instance will have its own set of outputs prefixed with the resource name you chose in Instruqt.
#!/bin/bash
# Example challenge check script
# SSH into the VM and check if a service is running
ssh -i /root/.ssh/gcp_vm_key \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
${GCP_VM_SSH_USERNAME}@${GCP_VM_EXTERNAL_IP} \
"systemctl is-active nginx" &> /dev/null
if [ $? -eq 0 ]; then
echo "Success: Nginx is running"
exit 0
else
echo "Error: Nginx is not running"
exit 1
fiInstruqt automatically destroys the VM when the sandbox ends. The module handles cleanup of:
- The compute instance
- Associated persistent disks
- The generated SSH key pair (from Terraform state)
Note: The VM's external IP is ephemeral and will be released automatically.
If you cannot connect to the VM:
-
Verify the VM is running:
gcloud compute instances list --filter="name:${SANDBOX_ID}" -
Check the external IP is accessible:
ping ${GCP_VM_EXTERNAL_IP} -
Verify SSH key permissions:
ls -la /root/.ssh/gcp_vm_key # Should show: -rw------- (600) -
Test SSH with verbose output:
ssh -vvv -i /root/.ssh/gcp_vm_key ${GCP_VM_SSH_USERNAME}@${GCP_VM_EXTERNAL_IP}
If the VM fails to create:
- Check that Compute Engine API is enabled in your project
- Verify service account has
compute.instances.createpermission - Check quota limits in your GCP project
- Review Terraform logs in Instruqt sandbox output
For issues with:
- This Terraform module: Open an issue in this repository
- Instruqt custom resources: See Instruqt documentation
- GCP Compute Engine: Consult Google Cloud documentation
See LICENSE file for details.