Skip to main content

Overview

Agones provides multiple security layers to protect your game server infrastructure. This guide covers authentication, authorization, encryption, and best practices for securing your Agones deployment.

mTLS for Allocations

What is mTLS?

Mutual TLS (mTLS) provides two-way authentication between the allocator service and clients. Both the server and client verify each other’s identities using certificates.

Configuring mTLS

By default, mTLS is enabled in the allocator service. The allocator uses certificates for secure communication:
# Allocator deployment with mTLS
apiVersion: apps/v1
kind: Deployment
metadata:
  name: agones-allocator
spec:
  template:
    spec:
      containers:
      - name: agones-allocator
        env:
        - name: DISABLE_MTLS
          value: "false"  # mTLS enabled (default)
        - name: DISABLE_TLS
          value: "false"  # TLS enabled (default)
        volumeMounts:
        - name: tls-cert
          mountPath: /home/allocator/tls/
        - name: client-ca
          mountPath: /home/allocator/client-ca/
The allocator looks for TLS certificates in /home/allocator/tls/ and client CA certificates in /home/allocator/client-ca/.

Certificate Rotation

Agones automatically watches for certificate changes and reloads them without downtime:
// From cmd/allocator/main.go:331-346
if !h.mTLSDisabled {
    cancelCert, err := fswatch.Watch(logger, certDir, time.Second, func() {
        h.certMutex.Lock()
        defer h.certMutex.Unlock()
        caCertPool, err := getCACertPool(certDir)
        if err != nil {
            logger.WithError(err).Error("could not load CA certs; keeping old ones")
            return
        }
        h.caCertPool = caCertPool
        logger.Info("CA certs updated")
    })
}
Certificates are monitored and automatically reloaded when updated, ensuring zero-downtime certificate rotation.

Client Configuration

Clients must present valid certificates when mTLS is enabled:
import (
    "crypto/tls"
    "crypto/x509"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
)

// Load client certificate
cert, err := tls.LoadX509KeyPair("client.crt", "client.key")
if err != nil {
    log.Fatal(err)
}

// Load CA certificate
caCert, err := os.ReadFile("ca.crt")
if err != nil {
    log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)

// Configure TLS
tlsConfig := &tls.Config{
    Certificates: []tls.Certificate{cert},
    RootCAs:      caCertPool,
}

// Create gRPC connection
creds := credentials.NewTLS(tlsConfig)
conn, err := grpc.Dial("allocator:443", grpc.WithTransportCredentials(creds))
Disabling mTLS removes authentication and should only be done in development environments.
To disable mTLS:
helm install agones agones/agones \
  --set agones.allocator.disableMTLS=true
Or via environment variable:
env:
- name: DISABLE_MTLS
  value: "true"

RBAC Configuration

Controller Service Account

The Agones controller runs with a dedicated service account with minimal required permissions:
# From install/helm/agones/templates/serviceaccounts/controller.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: agones-controller
  namespace: agones-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: agones-controller
rules:
- apiGroups: [""]
  resources: ["events"]
  verbs: ["create", "patch"]
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["create", "update", "delete", "list", "watch"]
- apiGroups: [""]
  resources: ["nodes", "secrets"]
  verbs: ["list", "watch"]
- apiGroups: ["agones.dev"]
  resources: ["gameservers", "gameserversets", "fleets"]
  verbs: ["create", "delete", "get", "list", "update", "watch"]
- apiGroups: ["agones.dev"]
  resources: ["fleets/status", "gameserversets/status"]
  verbs: ["update"]
The controller only has permissions for resources it directly manages. It cannot modify cluster-wide resources or access other namespaces’ secrets.

SDK Service Account

GameServer pods run with a minimal service account:
apiVersion: v1
kind: ServiceAccount
metadata:
  name: agones-sdk
  namespace: agones-system
This service account has no RBAC permissions by default, following the principle of least privilege.

Custom RBAC for Game Servers

If your game servers need to interact with Kubernetes:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: gameserver-reader
  namespace: default
rules:
- apiGroups: ["agones.dev"]
  resources: ["gameservers"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: gameserver-reader-binding
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: gameserver-reader
subjects:
- kind: ServiceAccount
  name: agones-sdk
  namespace: agones-system

Security Best Practices

Network Policies

Restrict network access to game servers:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: gameserver-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      agones.dev/role: gameserver
  policyTypes:
  - Ingress
  - Egress
  ingress:
  # Allow game traffic on configured ports
  - from:
    - ipBlock:
        cidr: 0.0.0.0/0
    ports:
    - protocol: UDP
      port: 7000-8000
  # Allow sidecar communication
  - from:
    - podSelector:
        matchLabels:
          app: agones-controller
    ports:
    - protocol: TCP
      port: 9357  # SDK gRPC port
    - protocol: TCP
      port: 9358  # SDK HTTP port
  egress:
  # Allow DNS
  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: UDP
      port: 53
  # Allow external game backend
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
    ports:
    - protocol: TCP
      port: 443

Pod Security Standards

Apply pod security standards to game server namespaces:
apiVersion: v1
kind: Namespace
metadata:
  name: game-servers
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Resource Limits

Always set resource limits to prevent resource exhaustion:
apiVersion: agones.dev/v1
kind: GameServer
metadata:
  name: secure-gameserver
spec:
  template:
    spec:
      containers:
      - name: game-server
        image: my-game:latest
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"

Secrets Management

Never hardcode credentials in game server containers or ConfigMaps.
Use Kubernetes Secrets for sensitive data:
apiVersion: v1
kind: Secret
metadata:
  name: game-credentials
type: Opaque
stringData:
  api-key: "your-api-key"
---
apiVersion: agones.dev/v1
kind: GameServer
spec:
  template:
    spec:
      containers:
      - name: game-server
        env:
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: game-credentials
              key: api-key
For enhanced security, integrate with external secret managers:

Image Security

  1. Use specific image tags (not latest):
image: us-docker.pkg.dev/my-project/game-servers/my-game:v1.2.3
  1. Enable image pull secrets for private registries:
spec:
  template:
    spec:
      imagePullSecrets:
      - name: registry-credentials
  1. Scan images for vulnerabilities in CI/CD pipeline
  2. Use distroless or minimal base images

Allocator Service Security

Restrict access to the allocator service:
apiVersion: v1
kind: Service
metadata:
  name: agones-allocator
  namespace: agones-system
spec:
  type: LoadBalancer
  loadBalancerSourceRanges:
  - "10.0.0.0/8"  # Only allow internal network
  ports:
  - port: 443
    targetPort: 8443
    protocol: TCP

Audit Logging

Enable Kubernetes audit logging to track allocation requests:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
  resources:
  - group: "allocation.agones.dev"
    resources: ["gameserverallocations"]
- level: Metadata
  resources:
  - group: "agones.dev"
    resources: ["gameservers", "fleets"]

Health Checks

The allocator exposes health endpoints for monitoring:
# Liveness probe
curl http://allocator:8080/live

# Readiness probe
curl http://allocator:8080/ready
From the source code (cmd/allocator/main.go:264-273):
health.AddReadinessCheck("allocator-agones-client", func() error {
    if !podReady {
        return errors.New("asked to shut down, failed readiness check")
    }
    _, err := agonesClient.ServerVersion()
    if err != nil {
        return fmt.Errorf("failed to reach Kubernetes: %w", err)
    }
    return nil
})

Security Checklist

1

Enable mTLS

Ensure mTLS is enabled for allocator service (default)
2

Configure RBAC

Use minimal service accounts with least-privilege permissions
3

Network Policies

Implement network policies to restrict pod-to-pod communication
4

Resource Limits

Set CPU and memory limits on all game server pods
5

Secrets Management

Use Kubernetes Secrets or external secret managers for credentials
6

Image Security

Use specific tags, private registries, and vulnerability scanning
7

Audit Logging

Enable Kubernetes audit logging for compliance
8

Regular Updates

Keep Agones, Kubernetes, and game server images updated

Build docs developers (and LLMs) love