Skip to main content
COSMICBYTEZLABS
NewsSecurityHOWTOsToolsTraining
StudyProjectsNewsletterHire MeAbout
Subscribe

Press Enter to search or Esc to close

News
Security
HOWTOs
Tools
Training
Study
Projects
Newsletter
Hire Me
About
RSS Feed
Reading List
Subscribe

Stay in the Loop

Get the latest security alerts, tutorials, and tech insights delivered to your inbox.

Subscribe NowFree forever. No spam.
COSMICBYTEZLABS

Your trusted source for IT intelligence, cybersecurity insights, and hands-on technical guides.

1794+ Articles
149+ Guides

CONTENT

  • Latest News
  • Security Alerts
  • HOWTOs
  • Checklists
  • Projects
  • Exam Prep

RESOURCES

  • Search
  • Browse Tags
  • Newsletter Archive
  • Reading List
  • RSS Feed

COMPANY

  • About Us
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CosmicBytez Labs. All rights reserved.

System Status: Operational
  1. Home
  2. Projects
  3. Gophish Phishing Simulation Lab: Security Awareness Testing in Docker
Gophish Phishing Simulation Lab: Security Awareness Testing in Docker
PROJECTIntermediate

Gophish Phishing Simulation Lab: Security Awareness Testing in Docker

Deploy a self-hosted phishing simulation platform using Gophish in Docker. Build real-world phishing campaigns, track user engagement, and run security awareness programs — all within an authorized lab environment.

Dylan H.

Projects

July 8, 2026
12 min read
3–5 hours

Tools & Technologies

GophishDockerDocker ComposeNGINXOpenSSL

Overview

Phishing remains the number-one initial access vector in real-world breaches. Understanding how these attacks are constructed — and testing whether your users can spot them — is a core responsibility for any security team. Gophish is an open-source phishing simulation framework written in Go. It gives you a clean web UI to build campaigns, craft convincing email templates, host credential-capture landing pages, and generate detailed analytics on who clicked what.

This project walks you through deploying Gophish inside Docker Compose with an NGINX reverse proxy for TLS termination, configuring a local SMTP relay, and running a complete simulated phishing campaign against a test group. By the end you'll have a reusable, containerized lab that you can safely run against internal users (with authorization) or against dummy accounts for red-team practice.

Legal & Ethical Notice: Only run phishing simulations against accounts and users you have explicit written authorization to test. Unauthorized phishing testing violates computer fraud laws in most jurisdictions. This lab is intended for authorized security awareness programs, internal red-team engagements, and controlled homelab environments.


Architecture

                        ┌──────────────────────────────────────┐
                        │           Docker Host                │
                        │                                      │
   Browser / Email      │  ┌──────────┐    ┌───────────────┐  │
   ──────────────────►  │  │  NGINX   │──► │   Gophish     │  │
   :443 (phish site)    │  │ (TLS)    │    │  :3333 admin  │  │
   :8443 (admin panel)  │  │          │──► │  :80   phish  │  │
                        │  └──────────┘    └───────┬───────┘  │
                        │                          │           │
                        │                  ┌───────▼───────┐  │
                        │                  │  SQLite DB    │  │
                        │                  │  (volume)     │  │
                        │                  └───────────────┘  │
                        │                                      │
                        │  ┌──────────────────────────────┐   │
                        │  │  Mailhog (local SMTP catcher)│   │
                        │  │  :1025 SMTP  :8025 web UI    │   │
                        │  └──────────────────────────────┘   │
                        └──────────────────────────────────────┘

Components:

ContainerRole
gophishCore platform — campaign management, tracking, analytics
nginxReverse proxy — TLS termination for both admin and phish listeners
mailhogLocal SMTP trap — catches all outbound emails so nothing escapes the lab

Using Mailhog as the SMTP relay ensures zero risk of accidentally emailing real people during development. Switch to a real SMTP relay only when you're ready to run an authorized live campaign.


Prerequisites

  • Docker Engine 24+ and Docker Compose v2
  • A Linux host (or WSL2 on Windows)
  • OpenSSL for generating self-signed certificates
  • A domain or /etc/hosts entry for your phishing domain (e.g. phish.lab.local)

Step 1 — Project Structure

Create the working directory:

mkdir -p ~/gophish-lab/{nginx,certs,gophish-data}
cd ~/gophish-lab

Your final layout will look like this:

gophish-lab/
├── docker-compose.yml
├── nginx/
│   └── nginx.conf
├── certs/
│   ├── admin.crt
│   ├── admin.key
│   ├── phish.crt
│   └── phish.key
└── gophish-data/          # auto-created by Docker volume

Step 2 — Generate TLS Certificates

Gophish needs separate TLS certificates for the admin panel and the phishing listener. In a real engagement you'd use Let's Encrypt; for the lab, self-signed certs are fine.

cd ~/gophish-lab/certs
 
# Admin panel cert (CN = localhost)
openssl req -x509 -newkey rsa:4096 -keyout admin.key -out admin.crt \
  -days 365 -nodes \
  -subj "/C=CA/ST=AB/L=Lab/O=CosmicBytez/CN=localhost"
 
# Phishing domain cert (CN = phish.lab.local)
openssl req -x509 -newkey rsa:4096 -keyout phish.key -out phish.crt \
  -days 365 -nodes \
  -subj "/C=CA/ST=AB/L=Lab/O=CosmicBytez/CN=phish.lab.local"
 
chmod 600 *.key

Step 3 — Gophish Configuration

Create a custom config.json that Gophish will use at startup. Save this as gophish-data/config.json:

{
  "admin_server": {
    "listen_url": "0.0.0.0:3333",
    "use_tls": true,
    "cert_path": "/etc/gophish/certs/admin.crt",
    "key_path": "/etc/gophish/certs/admin.key"
  },
  "phish_server": {
    "listen_url": "0.0.0.0:80",
    "use_tls": false,
    "cert_path": "",
    "key_path": ""
  },
  "db_name": "sqlite3",
  "db_path": "/opt/gophish/gophish.db",
  "migrations_prefix": "db/db_",
  "contact_address": "",
  "logging": {
    "filename": "",
    "level": ""
  }
}

We're terminating TLS at NGINX, so the Gophish phish listener runs plain HTTP internally. NGINX handles HTTPS on port 443 and proxies to Gophish:80.


Step 4 — NGINX Configuration

Create nginx/nginx.conf:

events {
    worker_connections 1024;
}
 
http {
    # ── Admin panel (port 8443 → Gophish :3333) ──────────────────────
    server {
        listen 8443 ssl;
        server_name localhost;
 
        ssl_certificate     /etc/nginx/certs/admin.crt;
        ssl_certificate_key /etc/nginx/certs/admin.key;
        ssl_protocols       TLSv1.2 TLSv1.3;
        ssl_ciphers         HIGH:!aNULL:!MD5;
 
        location / {
            proxy_pass          https://gophish:3333;
            proxy_ssl_verify    off;
            proxy_set_header    Host $host;
            proxy_set_header    X-Real-IP $remote_addr;
            proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto https;
        }
    }
 
    # ── Phishing site (port 443 → Gophish :80) ───────────────────────
    server {
        listen 443 ssl;
        server_name phish.lab.local;
 
        ssl_certificate     /etc/nginx/certs/phish.crt;
        ssl_certificate_key /etc/nginx/certs/phish.key;
        ssl_protocols       TLSv1.2 TLSv1.3;
        ssl_ciphers         HIGH:!aNULL:!MD5;
 
        location / {
            proxy_pass          http://gophish:80;
            proxy_set_header    Host $host;
            proxy_set_header    X-Real-IP $remote_addr;
            proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto https;
        }
    }
 
    # ── HTTP redirect ─────────────────────────────────────────────────
    server {
        listen 80;
        return 301 https://$host$request_uri;
    }
}

Step 5 — Docker Compose

Create docker-compose.yml:

services:
  gophish:
    image: gophish/gophish:latest
    container_name: gophish
    restart: unless-stopped
    volumes:
      - ./gophish-data:/opt/gophish
      - ./certs:/etc/gophish/certs:ro
    networks:
      - phishnet
    # Internal ports only — NGINX handles external exposure
    expose:
      - "3333"
      - "80"
 
  nginx:
    image: nginx:alpine
    container_name: gophish-nginx
    restart: unless-stopped
    ports:
      - "443:443"    # Phishing site (HTTPS)
      - "8443:8443"  # Admin panel (HTTPS)
      - "8080:80"    # HTTP → HTTPS redirect
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      - gophish
    networks:
      - phishnet
 
  mailhog:
    image: mailhog/mailhog:latest
    container_name: gophish-mailhog
    restart: unless-stopped
    ports:
      - "8025:8025"  # Mailhog web UI
      # SMTP port 1025 is internal only
    expose:
      - "1025"
    networks:
      - phishnet
 
networks:
  phishnet:
    driver: bridge

Step 6 — Launch the Stack

cd ~/gophish-lab
docker compose up -d

Watch the Gophish logs for the initial admin credentials:

docker logs gophish 2>&1 | grep -A2 "Please login"
# Output example:
# time="2026-07-08T..." level=info msg="Please login with the username admin and the password <RANDOM_PASSWORD>"

Copy that password — you'll need it for the first login. After logging in, you'll be prompted to change it.


Step 7 — Add a Local DNS Entry

So your browser resolves the phishing domain correctly:

# On the Docker host (and any test machines):
sudo tee -a /etc/hosts <<EOF
127.0.0.1  phish.lab.local
EOF

Step 8 — First Login & Admin Setup

  1. Open https://localhost:8443 in your browser (accept the self-signed cert warning)
  2. Log in with admin and the password from Step 6
  3. Set a strong password when prompted
  4. You'll land on the Gophish dashboard

Step 9 — Configure the Sending Profile (SMTP)

Sending Profiles tell Gophish how to deliver emails.

  1. Navigate to Sending Profiles → New Profile
  2. Fill in:
    • Name: Lab Mailhog
    • From: IT Security <security@phish.lab.local>
    • Host: mailhog:1025
    • Username / Password: leave blank (Mailhog accepts unauthenticated)
  3. Click Send Test Email — enter your own address and verify it appears in the Mailhog UI at http://localhost:8025
  4. Save the profile

Step 10 — Create a User Group (Target List)

  1. Navigate to Users & Groups → New Group
  2. Name it Lab Users
  3. Add test targets manually or import via CSV:
First Name,Last Name,Email,Position
Alice,Smith,alice@lab.local,Analyst
Bob,Jones,bob@lab.local,Developer
Carol,White,carol@lab.local,Manager
  1. Save the group

Step 11 — Build an Email Template

We'll simulate a password reset notification — a classic phishing lure.

  1. Navigate to Email Templates → New Template
  2. Name: Password Reset - IT
  3. Subject: [Action Required] Your Password Will Expire in 24 Hours
  4. Switch to HTML tab and paste:
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"></head>
<body style="font-family:Arial,sans-serif;color:#333;max-width:600px;margin:0 auto;padding:20px;">
  <div style="border-bottom:3px solid #0066cc;padding-bottom:10px;margin-bottom:20px;">
    <strong style="font-size:18px;">CosmicBytez IT Security</strong>
  </div>
  <p>Hello {{.FirstName}},</p>
  <p>Our systems have detected that your account password will expire in <strong>24 hours</strong>. 
  To avoid losing access to your account, please click the button below to reset your password immediately.</p>
  <div style="text-align:center;margin:30px 0;">
    <a href="{{.URL}}" style="background:#0066cc;color:white;padding:12px 28px;text-decoration:none;border-radius:4px;font-weight:bold;">
      Reset My Password
    </a>
  </div>
  <p style="font-size:12px;color:#999;">
    If you did not request this email, please contact the IT Help Desk immediately.<br>
    This link expires in 24 hours.
  </p>
  <hr style="border:none;border-top:1px solid #eee;margin-top:30px;">
  <p style="font-size:11px;color:#bbb;">IT Security Team — CosmicBytez Labs</p>
</body>
</html>

{{.FirstName}} and {{.URL}} are Gophish template variables. {{.URL}} automatically injects the tracking link for each recipient.

  1. Check Add Tracking Image to track email opens
  2. Save the template

Step 12 — Build a Landing Page

The landing page is what users see after clicking the link. We'll capture submitted credentials.

  1. Navigate to Landing Pages → New Page
  2. Name: Password Reset Form
  3. Click Import Site and paste this HTML:
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Password Reset — CosmicBytez IT</title>
  <style>
    body { font-family: Arial, sans-serif; background: #f0f2f5; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }
    .card { background: white; border-radius: 8px; padding: 40px; width: 360px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
    h2 { color: #0066cc; margin-top: 0; }
    label { font-size: 13px; color: #555; display: block; margin-top: 14px; }
    input { width: 100%; padding: 10px; margin-top: 4px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; }
    button { width: 100%; padding: 12px; margin-top: 20px; background: #0066cc; color: white; border: none; border-radius: 4px; font-size: 15px; cursor: pointer; }
    .note { font-size: 11px; color: #999; margin-top: 16px; text-align: center; }
  </style>
</head>
<body>
  <div class="card">
    <h2>Reset Your Password</h2>
    <p style="font-size:13px;color:#666;">Enter your current credentials to verify your identity and set a new password.</p>
    <form method="POST" action="">
      <label>Email Address</label>
      <input type="email" name="email" placeholder="you@cosmicbytez.ca" required>
      <label>Current Password</label>
      <input type="password" name="password" placeholder="••••••••" required>
      <label>New Password</label>
      <input type="password" name="new_password" placeholder="••••••••" required>
      <button type="submit">Reset Password</button>
    </form>
    <p class="note">Secured by IT Security · CosmicBytez Labs</p>
  </div>
</body>
</html>
  1. Enable Capture Submitted Data and Capture Passwords (for the lab)
  2. Set Redirect to https://www.google.com (to redirect after form submit — users won't immediately know they've been phished)
  3. Save the page

Step 13 — Launch a Campaign

  1. Navigate to Campaigns → New Campaign
  2. Fill in:
    • Name: Lab Phish Test 01
    • Email Template: Password Reset - IT
    • Landing Page: Password Reset Form
    • URL: https://phish.lab.local (your phishing domain)
    • Launch Date: now (or schedule it)
    • Sending Profile: Lab Mailhog
    • Groups: Lab Users
  3. Click Launch Campaign

Gophish immediately queues emails. Check Mailhog (http://localhost:8025) to confirm they arrived.


Testing the Campaign

Simulate a user clicking the link

  1. Open Mailhog at http://localhost:8025
  2. Click an email from the campaign
  3. Click the Reset My Password button in the email body
  4. You'll be redirected to https://phish.lab.local (accept the cert warning)
  5. Submit the fake credential form
  6. Observe the redirect to Google

Check campaign results

Back in the Gophish dashboard under Campaigns, click your campaign name:

EventWhat it means
Email SentGophish delivered the email to SMTP
Email OpenedTracking pixel loaded (email was opened)
Clicked LinkUser clicked the phishing URL
Submitted DataUser filled out and submitted the credential form

You'll see per-user timeline events and captured credentials (in the lab, these are dummy values).

Verify tracking pixel

# Check Gophish logs for open/click tracking events
docker logs gophish --tail 50 | grep -E "open|click|submit"

Step 14 — Export a Results Report

Gophish can export campaign results to CSV:

  1. Go to Campaigns → [Your Campaign] → Results
  2. Click the Export CSV button
  3. The export includes timestamps for each event type per user — useful for measuring campaign effectiveness

Deployment Notes

Running a live authorized campaign

When you're ready to run against real users (with authorization), swap out Mailhog for a real SMTP relay:

// In the Gophish Sending Profile:
{
  "Host": "smtp.yourprovider.com:587",
  "Username": "your-smtp-user",
  "Password": "your-smtp-password"
}

Also replace the self-signed certificates with Let's Encrypt certificates for the phishing domain — users are much more likely to interact with a valid HTTPS site:

# On a public-facing server (not the lab):
certbot certonly --standalone -d phish.yourdomain.com

Data persistence

Campaign data lives in /opt/gophish/gophish.db inside the container, which is mapped to ./gophish-data/ on the host. Backups are simple:

cp ~/gophish-lab/gophish-data/gophish.db ~/gophish-db-backup-$(date +%F).db

Restricting admin panel access

In production, never expose the Gophish admin port publicly. Restrict it to localhost and use an SSH tunnel for remote access:

# On your local machine:
ssh -L 8443:localhost:8443 user@yourserver
# Then browse https://localhost:8443

Extensions & Next Steps

1. Spear Phishing Variants

Customize email templates per target role. Gophish supports template variables beyond {{.FirstName}} — you can reference {{.LastName}}, {{.Position}}, and {{.Email}} to personalize each message at scale.

2. SMS Phishing (Smishing) Awareness

Extend awareness training beyond email by using a test SMS gateway (e.g. Twilio in sandbox mode) with custom short links and training users to verify sender identity.

3. Multi-Scenario Campaigns

Build a library of templates covering common lures:

  • Shared document notifications (OneDrive/Google Drive spoofs)
  • HR policy updates requiring "immediate acknowledgment"
  • IT security alerts about suspicious login activity
  • Package delivery notifications

4. Integration with Wazuh / SIEM

Forward Gophish campaign events to your SIEM for correlation. If a user clicks a phishing link during a real-world campaign, Wazuh can alert and correlate that event with other IOCs on the same endpoint.

# Tail Gophish access logs and pipe to syslog forwarder
docker logs -f gophish | logger -t gophish

5. Phishing Awareness Training Workflow

Build a full cycle:

  1. Run a baseline phishing campaign (measure susceptibility)
  2. Identify users who clicked/submitted — enroll in awareness training
  3. Run a follow-up campaign 30 days later to measure improvement
  4. Report metrics to management: click rates before/after training

6. GoReport — Automated PDF Reports

GoReport is a Python tool that pulls Gophish campaign data via the API and generates formatted PDF reports — useful for delivering results to stakeholders.

pip install goreport
goreport --gophish-api-key <your-api-key> --campaign-id 1 --report-format pdf

Troubleshooting

IssueFix
Gophish container exits on startCheck docker logs gophish — often a malformed config.json or missing cert files
Can't reach admin panelConfirm NGINX is running: docker ps. Try curl -k https://localhost:8443
Emails not appearing in MailhogVerify Gophish sending profile host is mailhog:1025 (container DNS name)
Phish site cert warningExpected — self-signed certs trigger browser warnings. Accept or install cert into trusted store
Tracking pixels not registeringSome email clients block remote images. Email opens will show as 0 for those clients
Campaign link redirects to wrong URLVerify the URL field in the campaign matches your NGINX phish domain exactly

Summary

You now have a fully functional, containerized Gophish phishing simulation lab with:

  • Gophish for campaign management, tracking, and analytics
  • NGINX for TLS termination and port separation
  • Mailhog for safe local email capture during development

This setup gives you everything you need to conduct authorized security awareness assessments, measure user susceptibility over time, and build a data-driven training program. Swap Mailhog for a live SMTP relay and self-signed certs for Let's Encrypt when you're ready to move from lab to production campaigns.

#phishing#security-awareness#gophish#docker#red-team#social-engineering#homelab

Related Articles

OWASP DefectDojo: Self-Hosted Vulnerability Management Platform

Aggregate, deduplicate, and track security findings from 100+ scanners in a unified dashboard. Build a production-grade vulnerability management pipeline...

10 min read

OpenCTI: Building a Cyber Threat Intelligence Platform in Your Homelab

Deploy OpenCTI to aggregate, correlate, and visualize threat intelligence from MISP, NVD, AlienVault OTX, and Shodan — all in a self-hosted Docker stack.

12 min read

Building a SOAR Platform with Shuffle in Your Homelab

Deploy Shuffle, the open-source SOAR platform, to automate security workflows and orchestrate your homelab tools — from Wazuh alerts to enrichment lookups...

11 min read
Back to all Projects