Skip to main content
Configure GZCTF platform-wide settings including appearance, email, storage, containers, and security.

Configuration Overview

GZCTF uses a hybrid configuration system:

Database Config

Settings stored in database (editable via admin UI):
  • Platform appearance
  • Account policies
  • Container policies

File Config

Settings in appsettings.json (requires restart):
  • Email/SMTP
  • Storage backends
  • Container provider
  • Telemetry
Configuration changes via API/UI are applied immediately. Changes to appsettings.json require service restart.

Global Settings

Access: Admin PanelSettingsGlobal Config

Platform Branding

Title
string
default:"GZ"
Platform name prefix (e.g., “GZ” → “GZ::CTF”)
Slogan
string
default:"Hack for fun not for profit"
Tagline displayed on homepage
Description
string
default:"GZ::CTF is an open source CTF platform"
Meta description for SEO
Footer text (supports Markdown). Add links to social media, terms of service, etc.
{
  "GlobalConfig": {
    "Title": "MyUniversity",
    "Slogan": "Learn by Breaking",
    "Description": "Official CTF platform of MyUniversity Security Lab",
    "FooterInfo": "© 2024 MyUniversity | Privacy Policy"
  }
}

Logo and Favicon

Customize platform visuals:
1

Upload Logo

Click Update Logo in settings
2

Image Requirements

  • Maximum size: 3 MB
  • Recommended: PNG with transparency
  • Logo scaled to 640px width
  • Favicon scaled to 256×256px
3

Apply Changes

Logo and favicon update immediately
curl -X POST https://your-gzctf.com/api/admin/config/logo \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "[email protected]"

Theme Customization

CustomTheme
string
CSS hex color for primary theme color (e.g., #3B82F6 for blue)
Use your organization’s brand color for consistent visual identity.

Account Policy

Control user registration and authentication.
AllowRegister
boolean
default:true
Enable public user registration
ActiveOnRegister
boolean
default:true
Automatically activate accounts after registration (no email verification)
EmailConfirmationRequired
boolean
default:false
Require email verification for:
  • New registrations
  • Email address changes
  • Password resets
UseCaptcha
boolean
default:false
Enable CAPTCHA on registration and login forms
EmailDomainList
string
Comma-separated list of allowed email domains. Empty = allow all.Example: university.edu,student.edu
{
  "AccountPolicy": {
    "AllowRegister": true,
    "ActiveOnRegister": false,
    "EmailConfirmationRequired": true,
    "UseCaptcha": true,
    "EmailDomainList": "university.edu"
  }
}
If AllowRegister: false, users can only be created by admins via batch import.

Container Policy

Manage container resource allocation.
AutoDestroyOnLimitReached
boolean
default:false
Automatically destroy oldest container when team reaches limit
MaxExerciseContainerCountPerUser
integer
default:1
Maximum exercise (non-game) containers per user
DefaultLifetime
integer
default:120
Default container lifetime in minutes (range: 1-7200)
ExtensionDuration
integer
default:120
Additional minutes added when container is extended (range: 1-7200)
RenewalWindow
integer
default:10
Minutes before expiry when extension is allowed (range: 1-360)
{
  "ContainerPolicy": {
    "DefaultLifetime": 30,
    "ExtensionDuration": 15,
    "RenewalWindow": 5
  }
}
// Containers: 30min initial, +15min extensions, renew in last 5min

Email Configuration

Configure SMTP for email notifications.
Email settings are in appsettings.json and require service restart.

SMTP Setup

Edit appsettings.json:
{
  "EmailConfig": {
    "UserName": "[email protected]",
    "Password": "your-app-password",
    "SenderAddress": "[email protected]",
    "SenderName": "GZCTF Platform",
    "Smtp": {
      "Host": "smtp.gmail.com",
      "Port": 587,
      "BypassCertVerify": false
    }
  }
}
BypassCertVerify
boolean
default:false
Skip SSL certificate validation (use only for testing with self-signed certs)
Never commit passwords to version control. Use environment variables:
export EmailConfig__Password="your-password"

Storage Configuration

GZCTF supports multiple storage backends for files and attachments.

Local Storage (Default)

Store files on server filesystem:
{
  "StorageConfig": {
    "Type": "LocalStorage",
    "LocalStorage": {
      "Path": "/app/files"
    }
  }
}
Local storage path must be writable by the GZCTF process. Use Docker volume for persistence.

Object Storage (S3-Compatible)

Use S3, MinIO, or compatible services:
{
  "StorageConfig": {
    "Type": "S3Storage",
    "S3Storage": {
      "Endpoint": "s3.amazonaws.com",
      "Bucket": "gzctf-files",
      "Region": "us-east-1",
      "AccessKey": "YOUR_ACCESS_KEY",
      "SecretKey": "YOUR_SECRET_KEY"
    }
  }
}
Object storage is recommended for production deployments with multiple replicas.

Container Provider

Configure Docker or Kubernetes for challenge containers.

Docker Provider

{
  "ContainerProvider": {
    "Type": "Docker",
    "PortMappingType": "Default",
    "PublicEntry": "your-domain.com",
    "EnableTrafficCapture": false,
    "DockerConfig": {
      "Uri": "unix:///var/run/docker.sock"
    }
  }
}
PublicEntry
string
required
Public hostname/IP where containers are accessible
PortMappingType
enum
default:"Default"
  • Default: Map to host ports (requires open port range)
  • PlatformProxy: Proxy via WebSocket (no open ports needed)

Kubernetes Provider

{
  "ContainerProvider": {
    "Type": "Kubernetes",
    "PortMappingType": "Default",
    "PublicEntry": "k8s-cluster.com",
    "EnableTrafficCapture": true,
    "KubernetesConfig": {
      "Namespace": "gzctf-challenges",
      "KubeConfig": "/app/kube-config.yaml",
      "AllowCidr": [
        "10.0.0.0/8",
        "172.16.0.0/12"
      ],
      "Dns": [
        "8.8.8.8",
        "8.8.4.4"
      ]
    }
  }
}
AllowCidr
array[string]
Network policies for container egress
Dns
array[string]
Custom DNS servers for containers
Kubernetes mode requires:
  • Valid kubeconfig file
  • Proper RBAC permissions
  • Network policies configured

Container Registry

Configure authentication for private registries:
{
  "Registry": {
    "docker.io": {
      "ServerAddress": "https://index.docker.io/v1/",
      "UserName": "your-username",
      "Password": "your-password"
    },
    "ghcr.io": {
      "ServerAddress": "https://ghcr.io",
      "UserName": "github-username",
      "Password": "github-token"
    }
  }
}
Registry credentials are used to pull private container images for challenges.

Captcha Configuration

Protect against bots with CAPTCHA.

Cloudflare Turnstile

{
  "CaptchaConfig": {
    "Provider": "CloudflareTurnstile",
    "SiteKey": "your-site-key",
    "SecretKey": "your-secret-key"
  }
}
1

Get Turnstile Keys

Visit Cloudflare Turnstile to create site
2

Configure Keys

Add site key and secret key to config
3

Enable in Account Policy

Set UseCaptcha: true in admin settings

Hash Proof-of-Work

Alternative CAPTCHA using client-side computation:
{
  "CaptchaConfig": {
    "Provider": "HashPow",
    "HashPow": {
      "Difficulty": 18
    }
  }
}
Difficulty
integer
default:18
Number of leading zero bits (range: 8-48). Higher = harder to solve.
HashPow doesn’t require external services but may slow down registration on slow clients.

Security Settings

API Encryption

ApiEncryption
boolean
default:false
Enable asymmetric encryption for sensitive API requests (flag submissions)
When enabled, client encrypts requests with server’s public key. Prevents flag interception via network sniffing.
1

Enable Encryption

Toggle ApiEncryption to true in Global Config
2

Key Generation

System automatically generates X25519 key pair
3

Client Configuration

Frontend automatically fetches public key from /api/config

Telemetry and Monitoring

Configure observability for production monitoring.

Prometheus Metrics

{
  "Telemetry": {
    "Prometheus": {
      "Enable": true,
      "TotalNameSuffixForCounters": true
    }
  }
}
Metrics endpoint: /metrics

OpenTelemetry

{
  "Telemetry": {
    "OpenTelemetry": {
      "Enable": true,
      "Protocol": "Grpc",
      "EndpointUri": "http://otel-collector:4317"
    }
  }
}

Grafana Loki Logging

{
  "GrafanaLoki": {
    "Enable": true,
    "EndpointUri": "http://loki:3100",
    "Labels": [
      { "Key": "app", "Value": "gzctf" }
    ],
    "PropertiesAsLabels": ["Environment"],
    "MinimumLevel": "Information"
  }
}
Combine Prometheus + Loki + Grafana for complete observability stack.

Forwarded Headers

Configure when behind reverse proxy:
{
  "ForwardedOptions": {
    "ForwardedHeaders": 5,  // X-Forwarded-For + X-Forwarded-Proto
    "ForwardLimit": 1,
    "KnownProxies": [
      "nginx-proxy-ip"
    ],
    "KnownNetworks": [
      "10.0.0.0/8"
    ]
  }
}
Incorrect forwarded headers configuration can break:
  • Rate limiting
  • IP-based access control
  • Audit logs

Configuration API

Manage settings programmatically:
Retrieve current configuration:
{
  "accountPolicy": {...},
  "globalConfig": {...},
  "containerPolicy": {...}
}
Update configuration:
PUT /api/admin/config

{
  "globalConfig": {
    "title": "NewTitle",
    "slogan": "New Slogan"
  }
}
Changes apply immediately (no restart needed).

Environment Variables

Override config with environment variables:
# Database connection
export ConnectionStrings__Database="Host=postgres;Database=gzctf"

# Email password
export EmailConfig__Password="smtp-password"

# Storage
export StorageConfig__Type="S3Storage"
export StorageConfig__S3Storage__AccessKey="key"

# Any config can be overridden
export GlobalConfig__Title="MyPlatform"
Use double underscores (__) to represent nested JSON structure.

Best Practices

Secure Secrets

  • Use environment variables for passwords
  • Never commit credentials to git
  • Rotate secrets regularly

Test Changes

  • Test SMTP before enabling email verification
  • Verify storage backend is accessible
  • Check container provider connectivity

Monitor Resources

  • Enable telemetry in production
  • Set up alerts for errors
  • Track container resource usage

Backup Configuration

  • Export database config regularly
  • Keep appsettings.json in version control (without secrets)
  • Document custom changes

Troubleshooting

  • Database changes: Apply immediately (verify in UI)
  • File changes: Require service restart
  • Clear browser cache after logo/theme changes
Check:
  • SMTP credentials are correct
  • Port is not blocked by firewall
  • EmailConfirmationRequired matches SMTP config
  • Test with telnet: telnet smtp.host.com 587
Verify:
  • Container provider is running
  • Network is accessible
  • Registry credentials (if private images)
  • Resource limits are reasonable
Confirm:
  • Storage path/bucket exists
  • Credentials are valid
  • Network connectivity to storage backend
  • Sufficient permissions

Next Steps

Creating Games

Start creating your first CTF

Monitoring

Set up competition monitoring

Build docs developers (and LLMs) love