---
title: Server
url: 'https://wiki.teletypegames.org/infrastructure/server'
markdown: 'https://wiki.teletypegames.org/infrastructure/server.md'
lang: en
date: '2026-09-14'
description: 'A single Ubuntu 24.04 LTS machine runs everything Teletype Games uses: the portal, the Git server, CI, the wiki, project management, analytics and the BBSes. Nearly every service is a Docker Compose stack, and Nginx is the entry point for all of them. This page is the public digest; the detailed o…'
taxonomy:
  tag:
    - howto
---

# Server

> A single Ubuntu 24.04 LTS machine runs everything Teletype Games uses: the portal, the Git server, CI, the wiki, project management, analytics and the BBSes. Nearly every service is a Docker Compose stack, and Nginx is the entry point for all of them. This page is the public digest; the detailed operations documentation is internal ([VPS assistant](https://wiki.teletypegames.org/infrastructure/vps-assistant)).

# Overview

```mermaid
graph LR
  Internet -->|HTTPS| Nginx
  Internet -->|SSH| Gitea
  Internet -->|telnet| BBS[BBSes]
  Internet -->|FTP| FTP[FTP server]
  Nginx --> Gitea
  Nginx --> Woodpecker
  Nginx --> WebApp[Teletype Games portal]
  Nginx --> Grav[Grav wiki]
  Nginx --> Redmine
  Nginx --> Matomo
  Nginx --> ResourceSpace
  Nginx --> UptimeKuma[Uptime Kuma]
  Nginx --> Grafana
  Nginx --> Authentik
  Nginx --> GoAccess
  Nginx --> Static[Static sites]
  Woodpecker -->|build + deploy| WebApp
  Statusbot --> Discord
  Updater --> Discord
  UptimeKuma --> Discord
  Grafana -->|alerts| Discord
```

# Services

| Service | What it does |
|---|---|
| [Nginx](https://nginx.org/) | Entry point for all web traffic, TLS termination with Let's Encrypt certificates, security headers, bot filtering. |
| [Gitea](https://wiki.teletypegames.org/infrastructure/gitea) | Self-hosted Git: repositories, code review, issues, package registry. Registration is closed. |
| [Woodpecker](https://wiki.teletypegames.org/infrastructure/woodpecker) | CI/CD engine integrated with Gitea. It also deploys the portal: push to master → tests → image build → database migration → container swap. |
| Teletype Games portal | Vue frontend + Rails API on the [WarpEngine](https://wiki.teletypegames.org/engines/warp-engine) catalog engine, backed by MySQL. Running in production mode from its own images since September 2026. |
| [Grav](https://getgrav.org/) | This wiki: a flat-file CMS whose content lives in a git repository. Alongside it run a fetcher (git sync via webhook) and the wiki's telnet BBS view. |
| [Redmine](https://www.redmine.org/) | Project management: tasks, bugs, milestones. |
| [Matomo](https://matomo.org/) | Privacy-friendly analytics for the public sites. |
| [ResourceSpace](https://www.resourcespace.com/) | Digital asset management: game art, audio, video, documents. |
| [Uptime Kuma](https://uptime.kuma.pet/) | Availability and certificate-expiry monitoring with Discord alerts. |
| [Grafana](https://wiki.teletypegames.org/infrastructure/grafana) | Monitoring UI: metric and log dashboards for the machine, containers, backups, ports, logs, and the team's Gitea, Redmine and CI activity. Data from Prometheus and Loki; sign in with a Gitea account. The server's alerts (CPU, memory, disk, inodes, swap, OOM, restart loops, databases, backup, certificates, CI) go to Discord as Grafana rules. |
| [Authentik](https://wiki.teletypegames.org/infrastructure/idp) | Central sign-in: one account per member for every system (OIDC, SAML, forward auth). |
| [GoAccess](https://goaccess.io/) | Real-time traffic report from the Nginx log, behind [Authentik](https://wiki.teletypegames.org/infrastructure/idp) sign-in. |
| [FTP server](https://wiki.teletypegames.org/infrastructure/ftp-server) | Anonymous, read-only FTP for the DOS tools: the [DOSINST](https://wiki.teletypegames.org/dos/dosinst) program store (`APPS`) and the [TTGWIKI](https://wiki.teletypegames.org/dos/ttgwiki) wiki export (`WIKI`), the C64 and Plus/4 shelves (`C64`, `PLUS4`), and the WarpEngine game files for any FTP client (`WARP`); the same tree over plain HTTP at archive.teletypegames.org. |
| [Model service](https://wiki.teletypegames.org/infrastructure/llm) | llama.cpp in router mode on the internal `interstack` network: small language models behind one OpenAI-compatible address, a key per caller. Today it runs Qwen3.5 0.8B, the model of the [BBS](https://wiki.teletypegames.org/services/teletype-bbs)'s SERMO and a general small model for any stack, and Gemma 3 270M on demand. |
| BBSes | Ten telnet boards and [TTG Gate BBS](https://wiki.teletypegames.org/services/ttg-gate-bbs) in front of them, the [BBS network](https://wiki.teletypegames.org/services/bbs-network): the [Teletype BBS](https://wiki.teletypegames.org/services/teletype-bbs), the [Impostor BBS](https://wiki.teletypegames.org/services/impostor-bbs), the [TTG Wiki BBS](https://wiki.teletypegames.org/services/wiki-bbs), [Alexandria BBS](https://wiki.teletypegames.org/services/alexandria-bbs), [Feedia BBS](https://wiki.teletypegames.org/services/feedia-bbs), [TTG Blog BBS](https://wiki.teletypegames.org/services/ttg-blog-bbs), [WarpEngine BBS](https://wiki.teletypegames.org/services/warp-engine-bbs), [Scriptorium BBS](https://wiki.teletypegames.org/services/scriptorium-bbs), [Commodex BBS](https://wiki.teletypegames.org/services/commodex-bbs) and [Pixelia BBS](https://wiki.teletypegames.org/services/pixelia-bbs). |
| Statusbot | Pascal Discord scheduler that opens weekly status threads. Outbound only. |
| Updater | Go service watching Gitea commits, wiki updates and Redmine issues, posting to Discord webhooks. Outbound only. |
| Static sites | `teletype.hu` (busybox httpd) and `enigmazene.hu` (Astro build served directly by Nginx). |

# Public addresses

| Address | Service |
|---|---|
| teletypegames.org | Teletype Games portal |
| git.teletypegames.org | [Gitea](https://wiki.teletypegames.org/infrastructure/gitea) (SSH on port 2222) |
| ci.teletypegames.org | [Woodpecker](https://wiki.teletypegames.org/infrastructure/woodpecker) CI |
| wiki.teletypegames.org | this wiki |
| pm.teletypegames.org | Redmine |
| assets.teletypegames.org | ResourceSpace |
| uptime.teletypegames.org | Uptime Kuma ([Authentik](https://wiki.teletypegames.org/infrastructure/idp) sign-in; monitor.teletypegames.org and monitor.teletype.hu redirect here) |
| grafana.teletypegames.org | [Grafana](https://wiki.teletypegames.org/infrastructure/grafana) (Gitea sign-in) |
| ftp.teletypegames.org | [FTP server](https://wiki.teletypegames.org/infrastructure/ftp-server) (port 21) |
| teletype.hu, enigmazene.hu | static sites |

The legacy `*.teletype.hu` and `*.vps.teletype.hu` names redirect to their `teletypegames.org` counterparts. Open ports are listed on [Server ports](https://wiki.teletypegames.org/infrastructure/server-ports).

# How it runs

- **Docker Compose stacks**: every service has its own directory and compose file; most are git checkouts, so the configuration is version-controlled. A shared Makefile starts, stops and updates all of them.
- **Every image is pinned to a version**; no `latest` for external images. Updates are manual, monthly, preceded by a database dump.
- **Container ports bind to localhost only**; everything reaches the internet through Nginx. The exceptions are Gitea SSH and the three telnet BBSes.
- **Automatic security updates** (unattended-upgrades) on the host; a manual reboot after kernel updates.
- **Configuration under version control**: the Nginx config in its own git repository, the rest of `/etc` via etckeeper.

# Security

- TLS everywhere, HSTS and the usual security headers; hidden files (`.git`, `.env`) blocked on every vhost.
- Admin interfaces (container manager, database admins, Webmin, Prometheus, Loki) are **not on the internet**; they are reachable only through an SSH tunnel. [Grafana](https://wiki.teletypegames.org/infrastructure/grafana) is public, but sign-in is Gitea-only, with no password login.
- The firewall (ufw) denies by default; root cannot log in over SSH, only explicitly allowed admin accounts.
- fail2ban bans SSH, Gitea, Redmine and web brute-force attempts at the nftables level, so it covers container ports too.
- auditd logs administrative commands; AIDE verifies system-file integrity daily.
- The Git server rejects AI-training and scraper bots that ignore robots.txt by user agent; expensive Gitea paths (diff, blame, archives) are off-limits to all crawlers.
- Every application connects to its database with its own user, scoped to its own schema.

# Backups

Two chains: nightly database dumps (Gitea included) plus a mirror of every Gitea repository, followed by an rsync-based full mirror of all stacks, configuration and dumps to an off-site NAS. No versioning: the NAS always holds the latest state. Details: [Backup](https://wiki.teletypegames.org/infrastructure/backup).

# Retired services

| When | What | Note |
|---|---|---|
| 2026-10 | Netdata | its alerts became Grafana rules, Prometheus collects the metrics |
| 2026-09 | [Teletype Orbit](https://wiki.teletypegames.org/services/teletype-orbit) | stopped; source and data archived |
| 2026-09 | Wiki.js | the old wiki database; content now lives here in Grav |
| 2026-09 | OpenVPN | unused, disabled |
| 2026-09 | Countdowner | `countdown.teletype.hu` redirects to the portal |
| 2026-09 | Discourse forum | `forum.teletype.hu` redirects to the portal's contact page |

# Recent changes

- **2026-10-23** – [Gitea](https://wiki.teletypegames.org/infrastructure/gitea) (with its own database) and [Woodpecker](https://wiki.teletypegames.org/infrastructure/woodpecker) moved out of the portal's stack into stacks of their own; Traefik retired, Nginx proxies straight to every service.
- **2026-10-18** – Uptime Kuma moved to [uptime.teletypegames.org](https://uptime.teletypegames.org) (monitor.\* redirects; push and badge URLs keep working). Matomo moved to [matomo.teletypegames.org](https://matomo.teletypegames.org) (the old address redirects) and upgraded to 5.14. Matomo, Uptime Kuma and GoAccess moved behind [Authentik](https://wiki.teletypegames.org/infrastructure/idp) sign-in (the GoAccess password is gone); a sign-in lasts half a year. Grafana dashboards grouped by title prefix instead of folders.
- **2026-10-17** – Resource tuning: Netdata retired, its alerts moved to Grafana; 4 GB swap, a memory limit on every container, lighter Apache and cAdvisor load (the machine's CPU use dropped to about a third).
- **2026-10-16** – [Grafana](https://wiki.teletypegames.org/infrastructure/grafana) public at grafana.teletypegames.org with Gitea sign-in; new dashboards (backup, ports, TLS, uptime, databases, BBS, logs, Gitea, Redmine, CI); ufw rules narrowed to TCP.
- **2026-10-16** – Backup: restic retired, replaced by an rsync-based full file mirror to the NAS (`vps-backup-sync`); the Gitea database joined the nightly dumps.
- **2026-09-13** – GoAccess traffic report; bot filtering and robots.txt on the Git server; etckeeper.
- **2026-09-11** – Post-audit overhaul: container ports moved to localhost, admin UIs behind SSH tunnel, fail2ban, auditd, AIDE, restic backups, Netdata; the portal switched to production mode; image versions pinned; Redmine, Matomo and Uptime Kuma upgraded; Orbit and Wiki.js retired.
- **2026-09-10** – Gitea security incident (CVE-2026-59774), contained the same day, Gitea upgraded to 1.27.1.

'; var prevLevel = 2; for (var i = 0; i < headings.length; i++) { var h = headings\[i\]; var text = h.textContent.trim(); var slug = text.toLowerCase() .replace(/\[áàâä\]/g,'a').replace(/\[éèêë\]/g,'e').replace(/\[íìîï\]/g,'i') .replace(/\[óòôöő\]/g,'o').replace(/\[úùûüű\]/g,'u') .replace(/\[^a-z0-9\]+/g, '-').replace(/^-|-$/g, ''); if (!slug) slug = 'heading-' + i; if (used\[slug\]) { slug += '-' + i; } used\[slug\] = true; h.id = slug; var level = parseInt(h.tagName.charAt(1)); var cls = level > 2 ? ' class="toc-child"' : ''; html += '- [' + text + '](#'%20+%20slug%20+%20')
'; } html += '
'; toc.innerHTML = html; // Scroll-spy: highlight current heading var links = toc.querySelectorAll('a'); var ids = \[\]; for (var j = 0; j < links.length; j++) ids.push(links\[j\].getAttribute('href').slice(1)); function updateActive() { var current = ''; for (var k = 0; k < ids.length; k++) { var el = document.getElementById(ids\[k\]); if (el && el.getBoundingClientRect().top <= 80) current = ids\[k\]; } for (var m = 0; m < links.length; m++) { links\[m\].parentNode.classList.toggle('active', links\[m\].getAttribute('href') === '#' + current); } } window.addEventListener('scroll', updateActive, { passive: true }); updateActive(); })();

---

## Navigation

- Parent: [Infrastructure](https://wiki.teletypegames.org/infrastructure.md)
- Previous: [ResourceSpace](https://wiki.teletypegames.org/infrastructure/resourcespace.md)
- Next: [Server Ports](https://wiki.teletypegames.org/infrastructure/server-ports.md)
