Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/BaddKharma/redStack/llms.txt

Use this file to discover all available pages before exploring further.

With terraform.tfvars configured, you are ready to deploy. This page covers the four Terraform commands, what to expect at each step, and what happens on each instance during the 5-10 minute post-deploy initialization window.
AWS costs begin immediately. Two Elastic IPs are allocated and six EC2 instances start at terraform apply completion. Instances accrue charges 24/7 whether you are actively using the lab or not. Run terraform destroy when you are done to eliminate all charges. See the cost note at the bottom of this page.

Terraform commands reference

CommandWhat it does
terraform initDownloads provider plugins and initializes the working directory. Run once before anything else, or after adding new providers.
terraform planDry run. Shows exactly what Terraform will create, change, or destroy. No changes are made.
terraform applyProvisions the infrastructure defined in your .tf files. Prints the plan and prompts you to type yes before making any changes.
terraform destroyTears down all infrastructure managed by Terraform. Prompts for confirmation. Run this when you are done with the lab.

Deployment steps

1

Initialize Terraform

Download the AWS and random provider plugins and initialize the working directory:
terraform init
Expected output:
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.x.x...
Terraform has been successfully initialized!
If you see errors about missing providers or version constraints, ensure you are running Terraform 1.0 or higher (terraform --version) and that you have internet access from the machine running the command.
2

Review the deployment plan

Run a dry-run to see every resource Terraform will create before committing:
terraform plan
Review the plan output. You should see:
  • 50+ resources to be created
  • 6 EC2 instances: Mythic, Sliver, Havoc, Guacamole, Windows operator workstation, Apache redirector
  • 2 VPCs: team server VPC (10.50.0.0/16) and redirector VPC (10.60.0.0/16)
  • 2 Elastic IPs: one for Guacamole (public access portal), one for the redirector (C2 entry point)
  • Mythic, Sliver, and Havoc have no public IPs — they are internal only, reachable only through the redirector via VPC peering
  • Security groups, VPC peering connection, route tables, and network interfaces
  • 0 errors or warnings
If terraform plan reports errors, the most common causes are: missing required variables in terraform.tfvars, the rs-rsa-key key pair not existing in AWS, or insufficient IAM permissions. Fix the error before proceeding.
3

Deploy infrastructure

Apply the plan and provision all AWS resources:
terraform apply
Terraform prints the full plan and then prompts:
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:
Type yes and press Enter. Terraform begins creating resources in dependency order.Deployment takes approximately 10 minutes from yes to completion. Expected final output:
Apply complete! Resources: 50+ added, 0 changed, 0 destroyed.
Credentials, IPs, and SSH commands are printed automatically after apply completes. You can retrieve them again at any time with terraform output deployment_info.
4

Wait for user data scripts

Terraform completing does not mean the lab is ready. Every instance runs a user data script that installs and configures its software stack. Wait 5-10 minutes after terraform apply completes before attempting to connect.What each instance installs during user data:
  • Sets a descriptive hostname and populates /etc/hosts with all lab machine IPs and hostnames
  • Installs Docker Engine
  • Clones the Mythic repository to /opt/Mythic
  • Installs the Apollo agent and HTTP C2 profile
  • Starts approximately 10 Mythic Docker containers
  • Configures Mythic as a systemd service for auto-start on reboot (when enable_mythic_autostart = true)
  • Sets hostname and /etc/hosts entries
  • Downloads and installs the Sliver C2 server binary
  • Configures the Sliver daemon as a systemd service
  • Generates a pre-configured C2 profile with the correct X-Request-ID token at /home/admin/redstack-c2-profile.json
  • Configures firewall rules
  • Sets hostname and /etc/hosts entries
  • Installs Go (required to build Havoc from source)
  • Clones the Havoc repository and builds the teamserver binary
  • Installs an XFCE4 desktop environment and VNC server for GUI access through Guacamole
  • Configures the Havoc teamserver
  • Sets hostname and /etc/hosts entries
  • Installs Docker Engine
  • Deploys PostgreSQL, Guacamole daemon (guacd), and the Guacamole web application as Docker containers
  • Installs and configures Nginx as a reverse proxy for the Guacamole web UI
  • Pre-configures 7 Guacamole connections: Windows RDP, Mythic SSH, Guacamole SSH, Redirector SSH, Sliver SSH, Havoc SSH, and Havoc VNC desktop
  • Decrypts and stores the Windows Administrator password so RDP auto-connects without a password prompt
  • Configures WireGuard (when enable_external_vpn = true) for internal VPN routing
  • Disables Windows Defender real-time protection and Windows Firewall
  • Enables and configures RDP
  • Populates C:\Windows\System32\drivers\etc\hosts with lab machine hostnames
  • Installs Chromium, VS Code, MobaXterm, and 7-Zip via PowerShell
  • Pre-configures MobaXterm SSH sessions for all lab machines in a redStack Sessions folder (Mythic C2 (SSH), Sliver C2 (SSH), Havoc C2 (SSH), Apache Redirector (SSH), Guacamole Server (SSH))
  • Sets hostname and /etc/hosts entries
  • Installs Apache2 with mod_rewrite, mod_proxy, mod_proxy_http, mod_headers, and mod_ssl
  • Configures HTTP and HTTPS VirtualHosts with URI prefix routing for Mythic, Sliver, and Havoc
  • Configures header validation (X-Request-ID) — requests without the correct token receive a decoy CloudEdge CDN maintenance page
  • Downloads redirect.rules from the redRules repository (AV/scanner blocklist) when enable_redirector_htaccess_filtering = true
  • Generates a self-signed certificate with the redirector’s public IP as the Subject Alternative Name (used until Certbot replaces it)
  • Installs a connectivity test script at /home/admin/test_redirector.sh
  • Configures OpenVPN client and WireGuard server (when enable_external_vpn = true)
5

Review deployment outputs

After the post-deploy wait, retrieve all IPs, credentials, and SSH commands:
terraform output deployment_info
This prints a formatted block for each instance containing:
  • Public and private IP addresses
  • SSH commands (external via Elastic IP, internal via private IP)
  • Usernames and auto-generated passwords
  • Guacamole URL and admin credentials
  • C2 header name and token value
  • URI routing table (which prefix routes to which backend)
To see the network architecture diagram with your actual IPs filled in:
terraform output network_architecture
Save the output of terraform output deployment_info to a local file. You will reference IPs, credentials, and the C2 header token throughout the rest of the guide.
6

Point your domain to the redirector (open environments only)

Closed environment (HTB/VL/PG): Skip this step entirely. No domain or DNS record is needed. Proceed to verification.
For open environments with a registered domain, you must create DNS A records pointing to the redirector’s Elastic IP before running Certbot.Get the redirector’s Elastic IP from the output:
terraform output deployment_info
# Look for: APACHE REDIRECTOR > Public IP
Log into your DNS provider (Cloudflare, Namecheap, Route 53, etc.) and create A records:
TypeHostValueTTL
A@<Redirector Elastic IP>Automatic
Awww<Redirector Elastic IP>Automatic
A<subdomain><Redirector Elastic IP>Automatic
Only the apex @ record is required. Add www or custom subdomains if you want agents to call back over those hosts. Custom subdomains (e.g., cdn.yourdomain.tld, chat.yourdomain.tld) blend beacon traffic into patterns that look like legitimate service traffic.Verify DNS propagation after creating the records:
dig +short yourdomain.tld
The returned IP should match your redirector’s Elastic IP. DNS propagation can take a few minutes. Once it resolves correctly, proceed to Part 3 to run Certbot and obtain a trusted TLS certificate.

AWS EC2 Dashboard

The AWS EC2 Dashboard is your primary visibility tool for what Terraform has built. Use it to verify deployments and confirm clean teardowns after terraform destroy.
Make sure the AWS Console region (top-right dropdown) matches the region in your terraform.tfvars (us-east-1 by default). Resources created in one region are invisible when viewing another.
SectionLocationWhat to check
InstancesEC2 → Instances → InstancesAll 6 redStack instances should show running after apply. After terraform destroy, all should show terminated.
Elastic IPsEC2 → Network & Security → Elastic IPsTwo EIPs allocated at deploy time — one for Guacamole, one for the redirector. After terraform destroy, both should be released. Unreleased EIPs incur charges even with no instances attached.
Key PairsEC2 → Network & Security → Key PairsConfirm rs-rsa-key exists. Terraform does not create this — if it is missing, terraform apply will fail.
VPCsVPC → Your VPCsTwo VPCs are created: team server VPC (10.50.0.0/16) and redirector VPC (10.60.0.0/16). After terraform destroy, both should be removed.

AWS cost warning

Running EC2 instances accrue charges 24/7 whether you are actively using the lab or not. Forgetting a deployed lab is one of the most common causes of unexpected AWS bills.
  • Stop instances when not in use. Select all instances in the EC2 Dashboard → Instance State → Stop. This pauses compute charges but EBS volumes continue to accrue small storage charges.
  • The only way to eliminate all charges is terraform destroy. This terminates instances, releases both Elastic IPs, and removes all billable resources.
  • Estimated cost at default instance types (all running 24/7): t3.medium ×3 (~90/month)+t3.small×3( 90/month) + t3.small ×3 (~45/month) = approximately $135/month plus data transfer.
  • Set a billing alarm in the AWS Billing Console to alert you if monthly charges exceed a threshold you set. This is the best safeguard against forgotten resources.
Before redeploying after a terraform destroy, verify the destroy completed cleanly: check the EC2 Dashboard and confirm all redStack instances show terminated and no Elastic IPs remain allocated.