
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
├── docs/
│ └── ttp-to-runtime-rules.md # Observed attacker TTPs → Falco rules (eks-gitops, platform-engineering-lab)
├── 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
├── metrics/
│ ├── runtime-metrics.schema.json # Shared schema — identical across all 4 portfolio projects
│ └── runtime-metrics.json # Generated by scripts/export-honeypot-metrics.sh; gitignored, not committed
├── 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
│ ├── export-honeypot-metrics.sh # Queries Grafana/Loki, writes attacker_telemetry
│ └── emit-runtime-metrics.py # Wraps attacker_telemetry in the shared metrics schema
├── 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, metrics schema/export
├── 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.
Memory headroom after the container version bumps:
docker-compose.ymlpins newer Grafana (12.0.0), Loki, and Promtail (3.6.13) images than this droplet size was originally tuned against. Themem_limit/memswap_limitvalues per service are unchanged — watchdocker statsafter first deploy, and raise the droplet plan (or trim Loki'sretention_period/ Grafana's cache) if any container is consistently near its limit.
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: