Skip to content

TheSmithy Deployment

Ansible playbooks, Cloudflare DNS scripts, and deployment configuration for TheSmithy services. The unified playbook (ansible/staging-replication-playbook.yml) provisions both staging and sandbox environments on Ubuntu 24.04 LTS.

This document will be auto-updated by Minh when code changes are detected.

Playbook Overview

The playbook provisions an Evennia-based game server with the following defaults:

Variable Default Sandbox Override
environment_type development sandbox
git_branch main develop
domain_name the staging domain the sandbox domain
use_seed_db false true
auto_superuser false true
deploy_cascade false Set via sandbox-up.sh

Sandbox-specific defaults are stored in ansible/group_vars/sandbox.yml and applied with -e @group_vars/sandbox.yml.

Environment Types

Staging

Standard staging deployment. The playbook clones the repository (without force), deploys secret_settings_staging.py via the secret_settings.j2 template, and displays manual superuser creation instructions after provisioning.

Sandbox

Ephemeral, disposable environments created via the sandbox-up.sh script. Key differences from staging:

  • Git clone uses force: yes to overwrite any generated files.
  • Seed database: When use_seed_db is true, copies evennia_seed.db3 to evennia.db3 on first run (skipped if the database already exists).
  • Automatic superuser creation: When auto_superuser is true, runs tools/setup/create_superuser.py with credentials from DJANGO_SUPERUSER_USERNAME, DJANGO_SUPERUSER_EMAIL, and DJANGO_SUPERUSER_PASSWORD environment variables.
  • Sandbox secret settings: Deploys secret_settings_dev.py via the secret_settings_sandbox.j2 template, which uses SQLite, enables DEBUG, and configures ALLOWED_HOSTS with the sandbox public IP.
  • Cascade (UE5) server: Optionally deploys the Endless Cascade UE5 dedicated server as a systemd service.

Ansible Inventory

Staging

Edit ansible/inventory/hosts with target host details.

Sandbox

The template ansible/inventory/sandbox.ini.template is used by sandbox-up.sh to generate per-owner inventory files (sandbox-<owner>.ini). Placeholders replaced at launch:

  • __OWNER__ — sandbox owner name
  • __PUBLIC_IP__ — EC2 instance public IP
  • __SSH_KEY_PATH__ — path to the SSH private key
  • __CREATED_AT__ — UTC timestamp of creation

Cascade (UE5 Dedicated Server)

When deploy_cascade is true, the playbook:

  1. Opens port 17777 (TCP and UDP) in UFW.
  2. Deploys the endlesscascade.service systemd unit from endlesscascade.service.j2. The service starts after evennia.service and restarts on failure with a 15-second delay.
  3. Creates a CascadeServer Evennia account via tools/setup/create_cascade_account.py (requires cascade_password to be set).
  4. Streams the pre-built Cascade binary (~5.4 GB) from the dev server using SSH piped tar, skipping the transfer if the binary already exists at {{ cascade_dir }}/DeployedServer/LinuxServer/EndlessCascadeServer.sh.
  5. Enables the endlesscascade systemd service (started after Evennia is up).

Sandbox Scripts

Shell scripts in scripts/sandbox/ manage the full lifecycle of sandbox EC2 instances.

sandbox-up.sh

Creates an EC2 instance, generates an Ansible inventory, runs the playbook, and starts services.

sandbox-up.sh [--owner NAME] [--branch BRANCH] [--no-seed] [--no-cascade] [--yes]
Flag Description Default
--owner NAME Owner tag for the instance $USER
--branch BRANCH Git branch to deploy develop
--no-seed Skip copying the seed database seed enabled
--no-cascade Skip deploying the Cascade UE5 server cascade enabled
--yes Skip confirmation prompt interactive

sandbox-status.sh

Queries sandbox instance status from AWS and local state files.

sandbox-status.sh [--owner NAME]

Without --owner, lists all sandbox instances. With --owner, shows detailed connection info.

sandbox-down.sh

Terminates the EC2 instance, cleans up local state and inventory files.

sandbox-down.sh [--owner NAME] [--yes]

Configuration

AWS resource defaults are in scripts/sandbox/config/defaults.conf:

Setting Value
SANDBOX_AMI_ID ami-0e2c8caa4b6378d8c (Ubuntu 24.04 LTS, us-east-1)
SANDBOX_INSTANCE_TYPE t3.medium
SANDBOX_VOLUME_SIZE 30 GB
SANDBOX_MAX_INSTANCES 3
SANDBOX_CASCADE_DIR /home/ubuntu/cascade-server

Cost: ~$1.00/day per instance. Always tear down with sandbox-down.sh when done.

Ports

Port Protocol Service
4000 TCP Evennia Telnet
4001 TCP Evennia Web
4002 TCP Evennia WebSocket
4005 TCP Evennia Internal Web
17777 TCP/UDP Cascade UE5 Server (when deployed)

Cloudflare DNS Scripts

Scripts in deployment/keycloak/ and setup_grit_subdomain.sh manage Cloudflare DNS records for glassumbrella.io subdomains. All scripts authenticate with a scoped Cloudflare API token using Bearer authorization.

Required Environment Variable

export CLOUDFLARE_API_TOKEN="your-scoped-api-token"

Note: The legacy global API key (CLOUDFLARE_API_KEY) and email-header auth (CLOUDFLARE_EMAIL, X-Auth-Email/X-Auth-Key) were removed in MR !1045. All scripts now use Authorization: Bearer ${CLOUDFLARE_API_TOKEN}. Create a scoped token in Cloudflare under My Profile > API Tokens with Zone:DNS:Edit permissions.

deployment/keycloak/configure-cloudflare-dns.sh

Creates or updates the DNS A record for the Keycloak auth subdomain. Requires CLOUDFLARE_API_TOKEN; optionally accepts SERVER_IP, which defaults to the production server address defined in the script.

deployment/keycloak/update-cloudflare-dns.sh

Batch-updates DNS A records across multiple subdomains (@, auth, www, app) when the server IP changes. Requires CLOUDFLARE_API_TOKEN.

setup_grit_subdomain.sh

Creates the DNS A record for the Grit subdomain and prints manual instructions for nginx, SSL (Let's Encrypt), and Django ALLOWED_HOSTS configuration on the production server. Requires CLOUDFLARE_API_TOKEN.

Directory Structure

ansible/
├── staging-replication-playbook.yml
├── group_vars/
│   └── sandbox.yml
├── templates/
│   ├── nginx_site.j2
│   ├── secret_settings.j2
│   ├── secret_settings_sandbox.j2
│   ├── evennia.service.j2
│   └── endlesscascade.service.j2
└── inventory/
    ├── hosts
    └── sandbox.ini.template

deployment/keycloak/
├── configure-cloudflare-dns.sh
├── update-cloudflare-dns.sh
├── setup-keycloak-server.sh
├── configure-keycloak-realm.sh
├── configure-glass-umbrella-realm.sh
├── generate-saml-certificates.sh
├── lightweight-keycloak-setup.sh
├── check-aws-server-status.sh
├── recovery-after-reboot.sh
├── DEPLOYMENT_GUIDE.md
└── README.md

scripts/sandbox/
├── sandbox-up.sh
├── sandbox-down.sh
├── sandbox-status.sh
├── config/
│   └── defaults.conf
└── lib/
    ├── env_helpers.sh
    ├── aws_helpers.sh
    └── health_check.sh

setup_grit_subdomain.sh          # Root-level DNS + nginx setup for grit subdomain