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

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
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
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)
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"
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)")
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
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"
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
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
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.
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.