Concepts
Town OS is built around a set of core ideas. Understanding these concepts will help you make sense of how everything fits together — from defining a package to managing a running service.
Packages
A package is a self-contained YAML definition of a service, pulled from a git
repository. Each package specifies its networking port mappings, storage volumes,
environment variables, and interactive questions — everything needed to run the
service. Packages can run as containers (the default), QEMU-based virtual machines,
or Windows applications via Valve's Proton compatibility layer. File templates
(Go text/template files) can be rendered into volumes at install time
for dynamic configuration. Packages declare supplies tags (like
http, database, cache) to describe their
capabilities. The default repository ships with curated packages
covering git hosting, video conferencing, media streaming, team messaging,
and databases — with more being added regularly.
Questions
When you install a package, Town OS may present interactive prompts called questions.
Your responses fill @variable@ template placeholders throughout the package
definition — setting hostnames, ports, credentials, and other options. Each question
has a typed validator (hostname, port, bytes,
volume, archive, duration, secret,
or free-form text) and an optional default value, so configuration errors are caught
before the service ever starts. Several types auto-generate values when left empty:
ports are assigned randomly in the 10000–60000 range, hostnames are generated as
package-name-4hex, and secrets produce a 64-character hex string.
Services
Once a package is installed, it becomes a service — a running container managed by a systemd unit. Town OS gives you start, stop, and restart control, live log streaming via Server-Sent Events, cursor-based journal pagination, and the ability to enable or disable services. Services are isolated from each other and from the host system.
Networking
Town OS includes
rolodex,
a DNS server that manages authoritative zones for your packages and forwards
upstream queries. Each package declares its own port
mappings — external ports exposed to the host and internal
ports available only between containers. Port values support @variable@
templates so users can choose ports at install time. Packages that declare
dependencies share a network, allowing containers in the same dependency tree to
communicate directly. Parent packages can reference dependencies using
@dep_KEY_host@ and @dep_KEY_port_N@ template variables
in their environment, or via runtime environment variables
(TOWNOS_DEP_{KEY}_HOST and
TOWNOS_DEP_{KEY}_PORT_{port}). UPnP forwarding is handled
automatically.
Storage
All data is stored on btrfs subvolumes with per-package isolation. Each volume has
a mountpoint inside the container, a configurable quota (e.g. 512mb,
2gb), and optional uid/gid ownership. Volumes
can be pre-populated from container images using the archives feature,
or seeded by cloning a git repository into an empty volume at install time. Users
can also create their own standalone volumes. VM disk images are cached in a
dedicated subvolume so subsequent installs reuse them. Btrfs snapshots are supported
for point-in-time backups. Data persists across package reinstalls and upgrades —
your files are never lost when you update a service.
Repositories
Packages are organized into repositories — git repos containing a packages/
directory with versioned YAML definitions. Every Town OS installation includes the
default repository, but anyone can create and share custom repositories. Repositories
are ordered — later entries override earlier ones when package names collide. A
featured.json file can highlight selected packages in the UI.
Templates & Notes
The @variable@ template system connects user responses from questions to
environment variables, port mappings, volume quotas, and more. Built-in variables like
@LOCAL_EXTERNAL_HOST@ and @LOCAL_INTERNAL_HOST@ are always
available. After installation, notes display key metadata like connection
URLs, credentials, or contact information — with optional type validation for
url, phone, and email.
Pages
Town OS can host static websites. Each page has three possible source types: upload a tar archive, extract files from a container image, or clone a git repository. Every page gets its own domain and is served through Caddy. Archive pages can be updated by re-uploading; git and container image pages can be rebuilt on demand.
Monitoring
A built-in observability stack runs out of the box with no configuration required. Prometheus collects metrics and Node Exporter reports host statistics (CPU, memory, disk, network). Two monitoring backends are available: a lightweight built-in UI (default) or Grafana with auto-provisioned dashboards. The entire stack runs as system services and restarts automatically on failure.
Internationalization
All user-facing strings are routed through a message catalog keyed by BCP 47 locale
codes. 21 common languages are presented in their native scripts, with 87+ country-specific
codes available. Only English (en-US) is fully translated today —
the infrastructure is ready for community translations.
Accounts & Sessions
Town OS supports administrator and normal user accounts. Passwords require a minimum of 8 characters. Authentication uses JWT tokens with a 7-day inactivity expiration. Sessions are ephemeral — signing keys are regenerated on every reboot, which clears all active sessions automatically.
Audit Logging
Every administrative action is recorded with the account name, action, request path, detail, success flag, and timestamp. Read-only endpoints are excluded. The audit log supports pagination, filtering by account, and full-text search.
Settings
System-wide configuration is managed through key-value settings in the UI. Configurable values include the default volume quota (50 GB), max archive upload size (1 GB), archive unpack timeout (600s), locale, Proton runner image, and the DNS top-level domain.
Package Upgrades
Town OS automatically detects when newer package versions are available in your configured repositories. A badge on the dashboard shows the number of pending upgrades. You can dismiss versions you do not want — dismissals are tracked by a SHA256 hash so they reappear only when the upgrade set changes.
System Services
Infrastructure containers — monitoring, DNS, and the web UI — are managed separately
from user-installed packages. They use a distinct systemd prefix
(town-os-system--), always restart on failure, and cannot be disabled
by users.