How to harden a Quake AI virtual machine
Coming from another cloud?
▸AWS·EC2 Hardening
This Quake AI feature maps to AWS’s EC2 Hardening.
▸Azure·VM Security Baseline
This Quake AI feature maps to Azure’s VM Security Baseline.
▸DigitalOcean·Droplet Hardening
This Quake AI feature maps to DigitalOcean’s Droplet Hardening.
▸Google Cloud·OS Hardening
This Quake AI feature maps to Google Cloud’s OS Hardening.
How to harden a Quake AI virtual machine
Harden a freshly provisioned Linux virtual machine before it serves traffic. Restrict network access with security groups, reduce SSH exposure in the guest OS, add a host firewall, enable automatic security updates, and block repeated login attempts.
Start from a virtual machine you can SSH into. If you still need to create one, follow the production virtual machine provisioning guide first.
Prerequisites
- ConsoleLogged in to the Quake AI console
- CLIOpenStack CLI installed and authenticated (
clouds.yamloropenrcsourced)
Windows: CLI examples use bash. Set up a Linux CLI environment on Windows before proceeding.
- A running Linux virtual machine with working key-based SSH access
- The security group attached to the instance (note its name)
- Your admin workstation's public IP or CIDR (for SSH source scoping)
- Sudo on the VM
Step 1. Restrict the security group#
Security groups filter traffic before it reaches the instance. Remove broad rules, then add the ports your workload needs.
Target posture for a typical web VM:
| Direction | Protocol | Port | Source | Purpose |
|---|---|---|---|---|
| Ingress | TCP | 22 | ADMIN_CIDR | SSH from your admin network |
| Ingress | TCP | 80 | 0.0.0.0/0, reverse-proxy CIDR, or external edge CIDR | HTTP (if the VM serves web traffic) |
| Ingress | TCP | 443 | 0.0.0.0/0, reverse-proxy CIDR, or external edge CIDR | HTTPS (if the VM serves web traffic) |
| Egress | Any | Any | 0.0.0.0/0 | Outbound updates and API calls (default on custom groups) |
Replace ADMIN_CIDR with your office or home /32 (for example, 203.0.113.45/32). Use 0.0.0.0/0 for SSH only when you cannot name a narrower range.
Step 2. Create a non-root sudo user#
Run day-to-day work as an unprivileged account. Keep the bootstrap user (often ubuntu or cloud-user) until the new account works.
Connect from your workstation with the bootstrap user. Keep this session open through the remaining steps:
ssh BOOTSTRAP_USER@VM_FLOATING_IPThe SSH prompt confirms that the guest OS is ready for the following commands.
sudo adduser deploy
sudo usermod -aG sudo deploy
sudo mkdir -p /home/deploy/.ssh
sudo cp ~/.ssh/authorized_keys /home/deploy/.ssh/
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keysOpen a second SSH session and confirm key login as deploy before you disable root login in Step 3.
For a repeatable baseline, see the Configure a VM with Ansible template.
Step 3. Harden secure shell access#
Edit sshd_config, validate the syntax, and reload the daemon. Keep an existing session open while you test changes.
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
echo 'MaxAuthTries 3' | sudo tee -a /etc/ssh/sshd_config
sudo sshd -t
sudo systemctl reload sshOptional: change the SSH port only if your security group and host firewall rules already allow the new port. Update the security group before you change Port in sshd_config.
Step 4. Enable a host firewall#
A host firewall adds a second traffic filter behind the security group. A connection succeeds when both layers allow it.
sudo apt update
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
# Omit the next two rules when the VM does not serve web traffic.
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verboseStep 5. Enable automatic security updates#
Configure the guest OS to install security patches automatically. This covers unattended security fixes; plan reboot windows when kernels update.
sudo apt install -y unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgradesConfirm /etc/apt/apt.conf.d/50unattended-upgrades limits upgrades to security origins and that /etc/apt/apt.conf.d/20auto-upgrades contains:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";Step 6. Install fail2ban for SSH#
fail2ban watches authentication failures and temporarily blocks offending source IPs in the host firewall.
sudo apt install -y fail2ban
sudo tee /etc/fail2ban/jail.local <<'EOF'
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshdStep 7. Verify the hardening#
Run these checks from your workstation and on the VM.
Key-only SSH works for the sudo user:
ssh deploy@VM_FLOATING_IPThe SSH daemon refuses password login (expect Permission denied):
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no deploy@VM_FLOATING_IPIntended ports respond from the internet. From outside the VM, scan the floating IP:
nc -zv VM_FLOATING_IP 22
nc -zv VM_FLOATING_IP 80
nc -zv VM_FLOATING_IP 443
nc -zv VM_FLOATING_IP 3306Port 3306 (or another port you did not open) should fail to connect.
On the VM, confirm services:
sudo ss -tlnp
sudo systemctl is-active fail2banRelated documentation#
- Production virtual machine provisioning guide: launch workflow this page continues
- How to patch and update a Quake AI virtual machine: ongoing OS updates after hardening
- Security hardening checklist: project-wide audit list
- Security groups concept: how the Network service filters instance traffic
- How to create security group rules: rule fields and Console presets
- Configure a VM with Ansible: idempotent hardening playbook
Usage Guidelines
The sample code, software libraries, command line tools, proofs of concept, templates, and other related technology on this page (including any of the foregoing that is provided by Quake AI personnel) is provided to you as Quake AI Content under the Quake AI Customer Agreement, or the relevant written agreement between you and Quake AI (whichever applies). Do not use this Quake AI Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the Quake AI Content (such as sample code) as appropriate for production grade use based on your specific quality control practices and standards. Deploying Quake AI Content may incur Quake AI charges for creating or using Quake AI chargeable resources, such as running Compute instances or storing data in Object Storage. Your use is also subject to the Acceptable Use Policy.
For the full policy, see Usage Guidelines.
Last validated: 10.07.2026
Quick answers
- Why does `openstack image save` write a 0-byte file for my boot-from-volume instance?CLI
- Why does `openstack server create` fail with "Only volume-backed servers are allowed for flavors with zero disk"?CLIAPITerraform
- Why does my project still have a 10 GiB Cinder volume after I deleted my instance?CLIAPI