infra-edge-lab · v0.1.0
Showcase environment
tofu/envs/showcase is the skeleton of one long-lived public game server: a cloud server that is
never thrown away, behind its own tunnel, with a DNS-only name for the players. This page is the
hand-over to whoever brings it up: what the environment creates, which values they set, how they
apply it, and the one name it shares with the rest of the zone. At this version the environment
is validated, tested with mocked providers and planned without network access; it has never been
applied (README limitations).
What it creates
| Part | Value | Where it is set |
|---|---|---|
| Cloud server | one host, default edge-01 in the groups edge, db and fxserver; type cx23, image debian-13, location nbg1 (or fsn1); x86-64 only |
hosts, server_type, image, location in tofu/envs/showcase/variables.tf |
| Protection | delete and rebuild protection of the server and delete protection of its primary IPv4 address, always on (a fixed value, not a variable) | tofu/envs/showcase/main.tf, ADR 0014 |
| Primary IPv4 address | kept when the server is replaced, so that play stays valid; billed while it exists, also when unassigned |
hcloud_vm with use_primary_ip = true |
| Cloud firewall | ping; the game port 30120 for TCP and UDP only on a host in fxserver; never SSH |
hcloud_vm, game_port_open |
Tunnel show-edge |
show-web (public, nginx on 127.0.0.1:8080), show-ssh (SSH for machines, Access with a service token), show-tx (the game server’s admin panel on port 40120, Access login; only with a host in fxserver), show-status (a status page on another host, Access login; only with status_origin) |
tofu/envs/showcase/main.tf, tofu/envs/README.md |
play |
DNS-only A record of the primary IPv4 address: players connect to play.<zone> on port 30120 directly, because a tunnel cannot carry UDP |
address_records of cf_tunnel in tofu/envs/showcase/main.tf |
The host gets the same playbook as every environment (ansible/playbooks/site.yml): the base
hardening, the tunnel connector and nginx, MariaDB, the game server with txAdmin and the deploy
target, node_exporter and the backups. Ansible reaches it only through show-ssh
(configuration).
Values to set
OpenTofu reads these from secrets/showcase.enc.env (the keys of
secrets/env.example); the read-only plans of CI read
secrets/showcase-ci.enc.env:
| Value | Notes |
|---|---|
TF_VAR_zone, TF_VAR_account_id, TF_VAR_zone_id, TF_VAR_access_team_name |
the zone and the Cloudflare account; the zone is never written into the repository |
TF_VAR_allowed_emails |
who may log in to show-tx and show-status (JSON list) |
TF_VAR_ssh_public_key, SSH_PRIVATE_KEY_B64 |
the admin key; the private key only for the apply workflow |
CLOUDFLARE_API_TOKEN, HCLOUD_TOKEN |
a zone-limited Cloudflare token with the permissions that task preflight ENV=showcase prints, and a token of a cloud project that holds nothing but this lab |
AWS_ENDPOINT_URL_S3, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, TF_VAR_state_passphrase |
the state bucket and the state passphrase (ADR 0013) |
Variables of the environment with a default: hosts, server_type, location, image,
tunnel_name (show-edge), status_origin (null: no show-status), allowed_idps. Change
them in a *.tfvars file that stays out of git, or with TF_VAR_*.
Ansible needs ansible/inventories/showcase/group_vars/, which this version does not have.
Write it after the demo values, with every secret in a *.sops.yaml file
(ADR 0006):
- the game server of
luminare.gameserver: the build and the sha256 of its archive, the license key (secret), the mode (plainortxadmin), the number of slots and, for txAdmin, its own values; see that collection’s documentation; - the database and its accounts (
mariadb_databases, passwords secret); - the backups: an off-host repository (
restic_backup_repository), its password and the credentials of its backend, all secret (ADR 0027); - where the monitoring runs: Prometheus and the status page watch the showcase from another host,
so
status_originand the observability targets point at that host.
Apply
- Create the encrypted files and the GitHub environment
showcase(required reviewer) as in the runbook. - Run
task preflight ENV=showcase. It refuses when the zone holds a record namedshow-*orplaythat this repository did not create (see below). - Apply from the workstation with
task up ENV=showcase(it asks before the apply), or run theapplyworkflow withenv = showcase, which plans, checks the plan against the zone, waits for the reviewer, applies exactly that plan, then configures and smoke-tests the host throughshow-ssh. - Check
play.<zone>withdig +shortand a game client on port 30120.
task destroy and task rebuild refuse showcase. Taking it down is a deliberate manual step:
change the fixed protection in tofu/envs/showcase/main.tf in a reviewed change, apply it, then
destroy.
The name play
play is the only name outside show-* that showcase may write (the guard pattern
^(show-[a-z0-9-]+|play)$, ADR 0009), and the
only DNS-only record of this repository. It publishes the server’s IPv4 address, which UDP game
traffic needs; the provider’s basic DDoS protection is all that stands in front of it.
The same name may be wanted elsewhere in the zone, for example for a web page for players. The
zone can hold only one record set under play, so:
- before the first apply, the preflight refuses an existing
playrecord that this repository did not create; remove that record first, or - choose another name for the game address: change the label in
address_recordsintofu/envs/showcase/main.tf, the showcase pattern incf_tunnel,cf_access_appandscripts/cloudflare_api.py, and their tests, together with a new ADR that supersedes the name rules of ADR 0009. A page for players then lives under another name, outside this repository.
Before and after
Until the showcase exists, test on demo: it is thrown away after each use, has no play record
and is never protected. Once it exists, drift plans it every night and opens an issue when it
differs from the code (ADR 0023).
Licensed under Apache-2.0. Source: luminare-dev/infra-edge-lab at v0.1.0.