
Medium-interaction SSH/Telnet honeypot built with Cowrie, Loki, Promtail, and Grafana - provisioned on DigitalOcean via Terraform with a GitLab CI validation pipeline.
An SSH/Telnet honeypot stack deployed on a DigitalOcean droplet using Terraform. Attacks are captured by Cowrie, stored in Loki, and visualised in Grafana with a live world map of attack origins.
honeypot/
├── cowrie/
│ └── etc/
│ ├── cowrie.cfg # Cowrie honeypot configuration
│ └── userdb.txt # Accepted and rejected fake credentials
├── geoip/
│ └── .gitkeep # Placeholder - MMDB files are gitignored
├── grafana/
│ ├── provisioning/
│ │ ├── dashboards/
│ │ │ ├── dashboards.yml # Provisioning: dashboard provider
│ │ │ └── honeypot-dashboard.json # Pre-built Attack Monitor dashboard
│ │ └── datasources/
│ │ └── loki.yml # Auto-provisioned Loki datasource
│ └── grafana.ini # Grafana server settings
├── loki/
│ └── config.yml # Loki single-binary config and retention
├── promtail/
│ └── config.yml # Promtail scrape and GeoIP pipeline
├── scripts/
│ ├── geoip-update.sh # Download or refresh GeoIP database
│ └── setup-firewall.sh # Host UFW rules for honeypot ports
├── terraform/
│ ├── templates/
│ │ ├── cloud-init.yaml.tftpl # Droplet first-boot script (Terraform-templated)
│ │ └── env.tftpl # `.env` lines embedded via Terraform
│ ├── backend.tf # Terraform backend config
│ ├── main.tf # Droplet, SSH key, firewall, cloud-init
│ ├── outputs.tf # IPs and helpful post-apply values
│ ├── terraform.tfvars.example # Example variable values (copy to terraform.tfvars)
│ ├── variables.tf # Terraform input variables
│ └── versions.tf # Terraform and provider version constraints
├── .env.example # Example environment file for manual setup
├── .gitignore # Ignored paths and files
├── .gitlab-ci.yml # CI/CD pipeline: fmt, validate, Checkov
├── docker-compose.yml # Docker Compose file for the honeypot stack
├── LICENSE # GPLv2 license
├── manual-deployment.sh # Legacy VM bootstrap without Terraform
└── README.md # Project documentation
Note: These requirements are based on the DigitalOcean Basic Droplet plan as of May 2026 and are the minimum requirements to run the project.
Note: After installation, it is recommended to open a new terminal and verify you can still SSH on
ADMIN_SSH_PORT(Default: 2022) before closing your original session.
Create an SSH key pair on your local machine and copy the public key path.
Go to the terraform directory then copy and edit the variables file:
Note:
do_token,ssh_public_key_path, andgrafana_admin_passwordmust be configured at minimum interraform.tfvarsbefore applying.
cd terraform
cp terraform.tfvars.example terraform.tfvars
Note: Terraform must be installed on your local machine. Visit Terraform Installation Guide for instructions.
terraform init # Initialize Terraform and download providers
terraform apply
terraform apply -replace="digitalocean_droplet.honeypot"
terraform destroy
Create a DigitalOcean droplet with the above hardware requirements and your SSH key.
SSH into the droplet or use the DigitalOcean web console and run the following commands:
ssh root@<your-droplet-ip> # If using DigitalOcean web console, skip this command
git clone https://gitlab.com/Oseguera12/cowrie-honeypot-digitalocean.git /opt/honeypot
cd /opt/honeypot
cp .env.example .env
nano .env
bash manual-deployment.sh
Note: By default, Terraform writes state to
terraform/terraform.tfstateon your local machine. This file contains sensitive output values (droplet IP, Grafana password, SSH key fingerprint) and must never be committed..gitignorecovers*.tfstateand*.tfstate.*.
Risks of local state:
apply runs can corrupt the fileFor anything beyond a personal lab, switch to a remote backend. terraform/backend.tf contains a commented-out DigitalOcean Spaces configuration (S3-compatible).
To enable remote backend:
Create a Spaces bucket in your DigitalOcean account
Generate a Spaces access key under API > Spaces Keys
Export the keys as environment variables (do not put them in terraform.tfvars):
export AWS_ACCESS_KEY_ID=<spaces-access-key>
export AWS_SECRET_ACCESS_KEY=<spaces-secret-key>
Uncomment the backend "s3" block in terraform/backend.tf and fill in your bucket name and region endpoint.
Run terraform init -migrate-state to move existing local state to Spaces.
.gitlab-ci.yml runs three jobs on every push in a single validate stage: