GCP Deployment Manager

Deploy secure Ubuntu instances on Google Cloud Platform using Deployment Manager and Cloud-Init

Advanced Level
45-60 minutes
Enterprise Security
RFS - Security Expert
RFS
eJPT, eCPPTv2, CRTP, ADCS CESP
Architecture Overview
Complete GCP infrastructure with security hardening and monitoring

Infrastructure Components

  • Compute Engine VM (e2-medium)
  • VPC Network with custom subnet
  • Static external IP address
  • Firewall rules (SSH, HTTP, HTTPS)
  • KMS-encrypted persistent disk

Security Features

  • SSH key-only authentication
  • UFW firewall configuration
  • Fail2Ban intrusion prevention
  • System hardening (sysctl)
  • Google Cloud Ops Agent
Prerequisites

Required Tools

  • Google Cloud SDK (gcloud CLI)
  • SSH key pair generated
  • Text editor (VS Code, vim, etc.)
  • Basic YAML knowledge

GCP Requirements

  • Active GCP project with billing
  • Compute Engine API enabled
  • Deployment Manager API enabled
  • IAM permissions for deployment
1
Create Deployment Manager Template
Create the main deployment template with all GCP resources

Create a file named deployment.yaml with the complete infrastructure definition:

resources:
- name: ubuntu-vm
  type: compute.v1.instance
  properties:
    zone: us-central1-a
    machineType: zones/us-central1-a/machineTypes/e2-medium
    disks:
    - deviceName: boot
      type: PERSISTENT
      boot: true
      autoDelete: true
      initializeParams:
        sourceImage: projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts
        diskType: zones/us-central1-a/diskTypes/pd-ssd
        diskSizeGb: 20
        diskEncryptionKey:
          kmsKeyName: projects/${PROJECT_ID}/locations/us-central1/keyRings/vm-encryption/cryptoKeys/vm-key
    networkInterfaces:
    - network: $(ref.vpc-network.selfLink)
      subnetwork: $(ref.subnet.selfLink)
      accessConfigs:
      - name: External NAT
        type: ONE_TO_ONE_NAT
        natIP: $(ref.static-ip.address)
    tags:
      items:
      - ubuntu-server
      - web-server
    serviceAccounts:
    - email: ${SERVICE_ACCOUNT_EMAIL}
      scopes:
      - https://www.googleapis.com/auth/cloud-platform
    metadata:
      items:
      - key: ssh-keys
        value: |
          ubuntu:${SSH_PUBLIC_KEY}
      - key: user-data
        value: |
          #cloud-config
          package_update: true
          package_upgrade: true
          
          packages:
            - ufw
            - fail2ban
            - unattended-upgrades
            - htop
            - curl
            - wget
            - git
            - vim
            - nginx
            - certbot
            - python3-certbot-nginx
            - google-cloud-ops-agent
            - aide
            - rkhunter
            - chkrootkit
            - lynis
          
          # Security hardening
          write_files:
            - path: /etc/ssh/sshd_config.d/99-security.conf
              content: |
                PermitRootLogin no
                PasswordAuthentication no
                PubkeyAuthentication yes
                AuthenticationMethods publickey
                MaxAuthTries 3
                ClientAliveInterval 300
                ClientAliveCountMax 2
                Protocol 2
                X11Forwarding no
                AllowTcpForwarding no
                PermitEmptyPasswords no
                PermitUserEnvironment no
                Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
                MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com
                KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group16-sha512
            
            - path: /etc/sysctl.d/99-security.conf
              content: |
                # Network security
                net.ipv4.ip_forward = 0
                net.ipv4.conf.all.send_redirects = 0
                net.ipv4.conf.default.send_redirects = 0
                net.ipv4.conf.all.accept_redirects = 0
                net.ipv4.conf.default.accept_redirects = 0
                net.ipv4.conf.all.accept_source_route = 0
                net.ipv4.conf.default.accept_source_route = 0
                net.ipv4.conf.all.log_martians = 1
                net.ipv4.conf.default.log_martians = 1
                net.ipv4.icmp_echo_ignore_broadcasts = 1
                net.ipv4.icmp_ignore_bogus_error_responses = 1
                net.ipv4.tcp_syncookies = 1
                net.ipv6.conf.all.accept_redirects = 0
                net.ipv6.conf.default.accept_redirects = 0
                
                # Kernel security
                kernel.dmesg_restrict = 1
                kernel.kptr_restrict = 2
                kernel.yama.ptrace_scope = 1
            
            - path: /etc/fail2ban/jail.local
              content: |
                [DEFAULT]
                bantime = 3600
                findtime = 600
                maxretry = 3
                
                [sshd]
                enabled = true
                port = ssh
                filter = sshd
                logpath = /var/log/auth.log
                maxretry = 3
                bantime = 3600
            
            - path: /etc/nginx/sites-available/default
              content: |
                server {
                    listen 80 default_server;
                    listen [::]:80 default_server;
                    server_name _;
                    
                    # Security headers
                    add_header X-Frame-Options DENY;
                    add_header X-Content-Type-Options nosniff;
                    add_header X-XSS-Protection "1; mode=block";
                    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
                    
                    root /var/www/html;
                    index index.html index.htm index.nginx-debian.html;
                    
                    location / {
                        try_files $uri $uri/ =404;
                    }
                    
                    # Hide server version
                    server_tokens off;
                }
            
            - path: /var/www/html/index.html
              content: |
                <!DOCTYPE html>
                <html>
                <head>
                    <title>Ubuntu Server - GCP Deployment</title>
                    <style>
                        body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
                        .container { max-width: 800px; margin: 0 auto; background: white; padding: 40px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
                        .header { text-align: center; margin-bottom: 30px; }
                        .status { background: #e8f5e8; padding: 20px; border-radius: 5px; margin: 20px 0; }
                        .info { background: #e3f2fd; padding: 15px; border-radius: 5px; margin: 10px 0; }
                    </style>
                </head>
                <body>
                    <div class="container">
                        <div class="header">
                            <h1>🚀 Ubuntu Server Deployed Successfully</h1>
                            <p>Your GCP Compute Engine instance is running Ubuntu 22.04 LTS</p>
                        </div>
                        <div class="status">
                            <h3>✅ Deployment Status: Active</h3>
                            <p>Server deployed via Google Cloud Deployment Manager with Cloud-Init</p>
                        </div>
                        <div class="info">
                            <h4>Security Features Enabled:</h4>
                            <ul>
                                <li>UFW Firewall configured</li>
                                <li>Fail2Ban intrusion prevention</li>
                                <li>SSH hardening applied</li>
                                <li>System monitoring active</li>
                                <li>Automatic security updates</li>
                            </ul>
                        </div>
                        <div class="info">
                            <h4>Installed Services:</h4>
                            <ul>
                                <li>Nginx Web Server</li>
                                <li>Google Cloud Ops Agent</li>
                                <li>Security monitoring tools</li>
                                <li>SSL/TLS ready (Certbot)</li>
                            </ul>
                        </div>
                    </div>
                </body>
                </html>
          
          runcmd:
            # Apply system hardening
            - sysctl -p /etc/sysctl.d/99-security.conf
            
            # Configure UFW firewall
            - ufw default deny incoming
            - ufw default allow outgoing
            - ufw allow ssh
            - ufw allow 'Nginx Full'
            - ufw --force enable
            
            # Start and enable services
            - systemctl restart ssh
            - systemctl enable fail2ban
            - systemctl start fail2ban
            - systemctl enable nginx
            - systemctl start nginx
            
            # Configure Google Cloud Ops Agent
            - systemctl enable google-cloud-ops-agent
            - systemctl start google-cloud-ops-agent
            
            # Initialize AIDE
            - aideinit
            - mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
            
            # Configure automatic security updates
            - echo 'Unattended-Upgrade::Automatic-Reboot "false";' >> /etc/apt/apt.conf.d/50unattended-upgrades
            - systemctl enable unattended-upgrades
            
            # Set up log rotation
            - logrotate -f /etc/logrotate.conf
            
            # Final security scan
            - lynis audit system --quick
          
          final_message: |
            Ubuntu server deployment completed successfully!
            
            Security features enabled:
            - UFW firewall configured
            - Fail2Ban active
            - SSH hardened
            - System monitoring active
            - Automatic updates enabled
            
            Access your server: ssh ubuntu@${EXTERNAL_IP}
            Web interface: http://${EXTERNAL_IP}

- name: vpc-network
  type: compute.v1.network
  properties:
    autoCreateSubnetworks: false
    routingConfig:
      routingMode: REGIONAL

- name: subnet
  type: compute.v1.subnetwork
  properties:
    region: us-central1
    network: $(ref.vpc-network.selfLink)
    ipCidrRange: 10.0.1.0/24
    privateIpGoogleAccess: true

- name: firewall-ssh
  type: compute.v1.firewall
  properties:
    network: $(ref.vpc-network.selfLink)
    allowed:
    - IPProtocol: TCP
      ports: ["22"]
    sourceRanges: ["0.0.0.0/0"]
    targetTags: ["ubuntu-server"]

- name: firewall-web
  type: compute.v1.firewall
  properties:
    network: $(ref.vpc-network.selfLink)
    allowed:
    - IPProtocol: TCP
      ports: ["80", "443"]
    sourceRanges: ["0.0.0.0/0"]
    targetTags: ["web-server"]

- name: static-ip
  type: compute.v1.address
  properties:
    region: us-central1

outputs:
- name: external-ip
  value: $(ref.static-ip.address)
- name: ssh-command
  value: ssh ubuntu@$(ref.static-ip.address)
- name: web-url
  value: http://$(ref.static-ip.address)
2
Create Parameters File
Define deployment parameters and configuration

Create deployment-config.yaml to customize your deployment:

imports:
- path: deployment.yaml

resources:
- name: ubuntu-deployment
  type: deployment.yaml
  properties:
    project-id: YOUR_PROJECT_ID
    service-account-email: YOUR_SERVICE_ACCOUNT@YOUR_PROJECT_ID.iam.gserviceaccount.com
    ssh-public-key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQ... your-public-key"
3
Prepare GCP Environment
Set up required APIs, permissions, and encryption keys

Run these commands to prepare your GCP environment:

# 1. Set up environment variables
export PROJECT_ID="your-project-id"
export DEPLOYMENT_NAME="ubuntu-secure-deployment"
export REGION="us-central1"
export ZONE="us-central1-a"

# 2. Enable required APIs
gcloud services enable compute.googleapis.com
gcloud services enable deploymentmanager.googleapis.com
gcloud services enable cloudkms.googleapis.com
gcloud services enable logging.googleapis.com
gcloud services enable monitoring.googleapis.com

# 3. Create KMS key for disk encryption
gcloud kms keyrings create vm-encryption --location=us-central1
gcloud kms keys create vm-key --location=us-central1 --keyring=vm-encryption --purpose=encryption

# 4. Create service account
gcloud iam service-accounts create ubuntu-vm-sa --display-name="Ubuntu VM Service Account"

# 5. Grant necessary permissions
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:ubuntu-vm-sa@$PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/monitoring.metricWriter"

gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:ubuntu-vm-sa@$PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/logging.logWriter"

# 6. Deploy the infrastructure
gcloud deployment-manager deployments create $DEPLOYMENT_NAME \
    --config=deployment.yaml \
    --description="Secure Ubuntu server with Cloud-Init"

# 7. Get deployment status
gcloud deployment-manager deployments describe $DEPLOYMENT_NAME

# 8. Get external IP
gcloud compute addresses describe static-ip --region=$REGION --format="value(address)"

# 9. Test SSH connection
ssh ubuntu@$(gcloud compute addresses describe static-ip --region=$REGION --format="value(address)")
4
Deploy Infrastructure
Execute the deployment and monitor progress

The deployment process will create all resources and configure the Ubuntu server with security hardening.

Deployment Timeline:

  • • Infrastructure creation: ~5-10 minutes
  • • Cloud-Init execution: ~15-20 minutes
  • • Security hardening: ~10-15 minutes
  • • Service configuration: ~5-10 minutes
5
Verify Deployment
Test connectivity and verify security configurations

Use these commands to verify your deployment:

# Check VM status
gcloud compute instances describe ubuntu-vm --zone=us-central1-a

# Check firewall rules
gcloud compute firewall-rules list --filter="network:vpc-network"

# Check Cloud Ops Agent status
gcloud logging logs list --filter="resource.type=gce_instance"

# Monitor system metrics
gcloud monitoring metrics list --filter="resource.type=gce_instance"

# Check security status on the VM
ssh ubuntu@YOUR_EXTERNAL_IP "sudo ufw status verbose"
ssh ubuntu@YOUR_EXTERNAL_IP "sudo fail2ban-client status"
ssh ubuntu@YOUR_EXTERNAL_IP "sudo systemctl status google-cloud-ops-agent"
6
Configure Monitoring & Alerts
Set up comprehensive monitoring and alerting

Monitoring Features

  • Google Cloud Ops Agent installed
  • System metrics collection
  • Application logs forwarding
  • Security event monitoring

Performance Optimization

  • SSD persistent disk
  • Optimized machine type
  • Network performance tuning
  • Resource monitoring
Troubleshooting Common Issues

Deployment Fails with Permission Errors

Ensure your service account has the required IAM roles:

  • • Compute Instance Admin (v1)
  • • Compute Network Admin
  • • Cloud KMS CryptoKey Encrypter/Decrypter
  • • Deployment Manager Editor

SSH Connection Refused

Check firewall rules and SSH configuration:

gcloud compute firewall-rules list --filter="name:firewall-ssh" gcloud compute instances get-serial-port-output ubuntu-vm --zone=us-central1-a

Cloud-Init Not Executing

Verify Cloud-Init logs on the instance:

sudo tail -f /var/log/cloud-init-output.log sudo cloud-init status --long
Frequently Asked Questions

How much does this deployment cost?

An e2-medium instance with 20GB SSD storage costs approximately $25-30/month. Use the GCP Pricing Calculator for accurate estimates.

Can I customize the security configuration?

Yes! Modify the Cloud-Init user-data section in the deployment template to add or remove security tools and configurations.

How do I scale this to multiple instances?

Use GCP Instance Groups or modify the template to create multiple VM resources with different names and configurations.

Is this suitable for production workloads?

This template includes enterprise-grade security hardening and is suitable for production use. Consider adding load balancers, backup strategies, and disaster recovery for critical workloads.

Next Steps & Enhancements

Infrastructure Enhancements

  • Add Cloud Load Balancer
  • Implement auto-scaling
  • Set up Cloud SQL database
  • Configure Cloud CDN

Security Improvements

  • Implement WAF protection
  • Add DDoS protection
  • Set up vulnerability scanning
  • Configure backup strategies

Ready to Deploy Your Secure Infrastructure?

Get the complete deployment package with all templates, configurations, and security hardening scripts.