Documentación de la API
Referencia completa de la API del systemcontroller de Town OS — 77 endpoints entre cuentas, almacenamiento, repositorios, paquetes, systemd, ajustes, auditoría, páginas, DNS, monitorización, servicios del sistema, idiomas, imágenes de máquina virtual y estado.
Visión general
El systemcontroller es el servicio central del backend de Town OS. Está construido sobre
Echo v5 y en producción escucha en el puerto 5309 (TCP) o
en un socket de dominio Unix. Todos los cuerpos de petición y respuesta usan JSON. Los
errores siguen el
RFC 9457
(application/problem+json).
CORS está habilitado para desarrollo. En producción, la API se sirve desde el mismo origen que la interfaz.
Autenticación
Autentícate llamando a POST /account/authenticate con un usuario y una
contraseña. La respuesta trae un token Bearer. Inclúyelo en las peticiones siguientes:
Authorization: Bearer <token> Las sesiones caducan a los 7 días de inactividad. Hay cinco niveles de autorización:
| Nivel | Descripción |
|---|---|
| Público | No requiere token. |
| Autenticado | Cualquier token de sesión válido. |
| Administrador | Token de sesión de una cuenta de administrador. |
| Concesión | Una concesión concreta en la cuenta deja pasar a quien no es administrador. Los extremos de almacenamiento de objetos toman la concesión de almacenamiento de objetos; el enrolamiento de pares toma la de wireguard, y el ámbito por red y la pertenencia de cada par los aplica el propio manejador. |
| Localhost | Las peticiones desde loopback pasan sin autenticarse — poder llegar a loopback ya significa estar en el ordenador — y cualquier otro origen necesita el nivel que aparece junto a la insignia. Lo usan los extremos de unidades y de registros de systemd, que lee el propio instrumental del controlador. |
Crear una partición de almacenamiento de objetos queda reservado a los administradores aunque los extremos de dentro de una partición no lo estén: una partición es la raíz de un árbol de permisos y reserva un subvolumen btrfs con cuota, así que la concesión te admite a los usuarios que hay dentro de una partición, no a la decisión de que deba existir.
Paginación
Todos los endpoints de listado aceptan estos parámetros de consulta y devuelven una envoltura común:
| Parámetro | Tipo | Descripción |
|---|---|---|
sort_by | string | Nombre del campo por el que ordenar. |
sort_order | string | asc o desc. |
limit | int | Tamaño de página (20 por omisión). |
offset | int | Desplazamiento de paginación. |
search | string | Coincidencia de subcadena, sin distinguir mayúsculas, sobre todos los campos de texto. |
Envoltura de la respuesta
{
"entries": [...],
"has_more": true,
"total_pages": 5,
"total_count": 97
} Estado
/status/ping Público
Comprobación de salud y visión general del sistema. Quien llame sin autenticarse recibe una
respuesta mínima con status y needs_setup. Quien llame autenticado
recibe los datos completos del panel, incluyendo el número de sistemas de ficheros, los
recuentos de paquetes, el resumen del estado de las unidades, el uso de disco, la IP externa
e interna y si hay actualizaciones disponibles.
Cuentas
/account/authenticate Público Autentica con usuario y contraseña. Devuelve un token de sesión y el objeto de la cuenta.
| Campo | Tipo | Descripción |
|---|---|---|
username | string | Obligatorio. Usuario de la cuenta. |
password | string | Obligatorio. Contraseña de la cuenta. |
/account/create Público
/
Administrador Crea una cuenta nueva. En modo de arranque inicial (cuando no existe ninguna cuenta de administrador habilitada), este endpoint es público. Si no, requiere autenticación de administrador. La primera cuenta creada se convierte en la administradora. La contraseña debe tener al menos 8 caracteres. El correo, el teléfono y el nombre real son obligatorios.
| Campo | Tipo | Descripción |
|---|---|---|
username | string | Obligatorio. |
password | string | Obligatorio. Mínimo 8 caracteres. |
email | string | Obligatorio. |
phone | string | Obligatorio. |
real_name | string | Obligatorio. |
admin | boolean | Si la cuenta tiene privilegios de administrador. |
/account Autenticado
Obtiene una sola cuenta por su usuario. Cuerpo de la petición:
{"username": "alice"}.
/account Autenticado Lista todas las cuentas. Admite parámetros de paginación.
/account/update Autenticado
Actualiza campos de una cuenta. Envía username para identificarla y un objeto
fields con cualquier combinación de password, email,
phone, real_name y admin. Solo se cambian los campos
que envíes.
/account/me Autenticado Devuelve el usuario asociado al token de la cabecera Authorization.
/account/sessions Autenticado Lista todas las sesiones activas del usuario autenticado. Cada sesión incluye su ID, el usuario, la hora de creación y la del último uso.
/account/session/revoke Autenticado
Revoca una sesión por su ID. Cuerpo de la petición:
{"session_id": "..."}.
/account/disable Administrador
Deshabilita una cuenta. Cuerpo de la petición:
{"username": "bob"}.
/account/enable Administrador
Vuelve a habilitar una cuenta deshabilitada. Cuerpo de la petición:
{"username": "bob"}.
Almacenamiento
/storage Autenticado
Lista los sistemas de ficheros. Además de los parámetros de paginación, acepta en el cuerpo
un name opcional (filtro por prefijo) y un state
(user, installed o uninstalled).
/storage/create Autenticado
Crea un subvolumen btrfs nuevo. Envía name y, si quieres, quota
(en bytes). Si la cuota es 0 o se omite, se usa el valor predeterminado del sistema (50 GB).
Los nombres reservados (installed, uninstalled,
archives) se rechazan.
/storage/modify Autenticado
Modifica un sistema de ficheros existente. Envía name para identificarlo y un
objeto filesystem con el name y/o la quota
actualizados.
/storage/remove Autenticado
Elimina un sistema de ficheros. Cuerpo de la petición:
{"name": "mydata"}.
/storage/upload-archive Administrador
Sube y descomprime un fichero dentro de un subvolumen de destino. Acepta
multipart/form-data con un campo subvolume y un fichero
archive. Admite .tar.gz, .tgz,
.tar.bz2, .tbz2, .tar.xz, .txz,
.tar, .zip y .7z.
| Campo | Tipo | Descripción |
|---|---|---|
subvolume | string | Obligatorio. Ruta del subvolumen de destino. |
archive | file | Obligatorio. Fichero comprimido que se va a subir. |
subpath | string | Opcional. Ruta relativa dentro del volumen donde descomprimir; se crea si hace falta. |
stop_service | string | Opcional. Nombre de la unidad de systemd que se detiene antes de descomprimir y se reinicia al terminar. |
| Ajuste | Por omisión | Descripción |
|---|---|---|
max_archive_size | 1 GB | Tamaño máximo de subida. |
archive_unpack_timeout | 600 segundos | Tiempo máximo para descomprimir. |
/storage/download-archive Administrador Descarga un fichero comprimido con el contenido de un subvolumen. Devuelve un fichero transmitido en el formato solicitado.
| Campo | Tipo | Descripción |
|---|---|---|
subvolume | string | Obligatorio. Ruta del subvolumen de origen. |
paths | string[] | Opcional. Array de rutas concretas dentro del subvolumen que se van a incluir. |
stop_service | string | Opcional. Nombre de la unidad de systemd que se detiene mientras se comprime y se reinicia después. |
format | string | Opcional. Formato de compresión: tar.gz (por omisión), tar.bz2 o tar.xz. |
filename | string | Opcional. Nombre base personalizado para el fichero descargado. El servidor le añade la extensión que corresponda. Por omisión, download. |
/storage/package-volumes Autenticado Lista los volúmenes de los paquetes agrupados por paquete, con la opción de incluir los volúmenes desinstalados.
/storage/remove-package-volume Administrador Borra un volumen concreto de un paquete usando su nombre interno.
/storage/remove-package-volume-group Administrador Borra en una sola llamada todos los volúmenes que pertenecen a un paquete, en lugar de quitarlos uno a uno por nombre interno.
Repositorios
/repository Autenticado Lista todos los repositorios de paquetes configurados, con su nombre, su URL y cualquier estado de error. Admite parámetros de paginación.
/repository/add Autenticado Añade un repositorio de paquetes nuevo. Dispara una actualización inmediata.
| Campo | Tipo | Descripción |
|---|---|---|
name | string | Obligatorio. Nombre visible del repositorio. |
url | string | Obligatorio. URL de git del repositorio. |
username | string | Opcional. Usuario de autenticación para repositorios privados. |
password | string | Opcional. Contraseña de autenticación para repositorios privados. |
/repository/remove Autenticado
Elimina un repositorio por su nombre. Dispara una actualización inmediata. Cuerpo de la
petición: {"name": "my-repo"}.
/repository/move Administrador
Reordena un repositorio a una posición nueva (empezando en cero). Los repositorios
posteriores prevalecen sobre los anteriores cuando los nombres de paquete chocan. Cuerpo de
la petición: {"name": "my-repo", "position": 0}.
/repository/refresh Autenticado Fuerza una actualización inmediata de los metadatos de todos los repositorios. Devuelve un cuerpo vacío si sale bien, o un objeto JSON que asocia nombres de repositorio a cadenas de error si alguno falla.
Paquetes
/packages Autenticado Lista todos los paquetes disponibles en todos los repositorios. Cada entrada incluye el repositorio, el nombre, la versión, la descripción, las etiquetas supplies, el estado de instalación y si hay una actualización disponible. Admite parámetros de paginación.
/packages/by-repo Autenticado
Lista los paquetes agrupados por repositorio. Acepta un parámetro de consulta
search opcional. Devuelve un array de grupos
{"repo": "...", "packages": [...]}.
/packages/installed Autenticado Lista los identificadores de los paquetes instalados. Admite parámetros de paginación.
/packages/installed/info Autenticado
Obtiene información detallada de un paquete instalado. Envía repo,
name y version. Devuelve las preguntas, las respuestas del
usuario, las notas y los tipos de nota.
/packages/responses Autenticado
Obtiene las respuestas guardadas de un paquete instalado. Envía repo,
name y version. Devuelve un mapa de clave y valor.
/packages/versions Autenticado
Lista las versiones disponibles de un paquete. Cuerpo de la petición:
{"name": "nginx"}. Devuelve un array de cadenas con los
identificadores de versión.
/packages/children Autenticado
Lista los paquetes hijos. Envía repo y name. Devuelve un array de
cadenas.
/packages/questions Administrador
Obtiene las preguntas de instalación de un paquete. Cuerpo de la petición:
{"name": "nginx"}. Devuelve un mapa de clave de pregunta a
{"query": "...", "type": "..."}.
/packages/questions/identity Administrador
Obtiene las preguntas de una versión concreta de un paquete. Envía repo,
name y version.
/packages/oauth/start Administrador
Inicia el flujo de dispositivo OAuth de una pregunta oauth. Envía
repo, name, version y question. El
controlador del sistema ejecuta el paso inicial del flujo contra el proveedor y devuelve
flow_id, approve_url (ábrela en el navegador del usuario), un
user_code opcional y interval_ms — cada cuánto sondear.
Las URL del proveedor vienen del paquete, no de Town OS, así que se comprueban antes de
llamarlas: solo https, y nunca una dirección de la propia red del anfitrión.
/packages/oauth/poll Administrador
Sondea un flujo iniciado arriba. Envía flow_id. Devuelve status:
pending mientras el usuario no haya aprobado, approved junto con
el token, o expired una vez que el flujo ha caducado o su token ya
se ha recogido — cada flujo es de un solo uso. El token después se envía como respuesta de
esa pregunta a /packages/install, igual que una respuesta escrita a mano.
/packages/install-preview Administrador
Muestra qué hará una instalación antes de comprometerse. Envía repo,
name y version. Devuelve los detalles de los volúmenes, las
asignaciones de puertos, el uso de disco, la información de cuotas, la versión de origen de
la actualización y un resumen legible.
/packages/install Administrador Instala un paquete.
| Campo | Tipo | Descripción |
|---|---|---|
repo | string | Obligatorio. Nombre del repositorio. |
name | string | Obligatorio. Nombre del paquete. |
version | string | Obligatorio. Versión que se va a instalar. |
responses | object | Obligatorio. Respuestas de clave y valor a las preguntas de instalación. |
reuse_volumes | boolean | Reutilizar los volúmenes de datos de una instalación anterior. |
import_from_version | string | Versión desde la que importar los volúmenes al actualizar. |
/packages/uninstall Administrador
Desinstala un paquete. Envía repo, name, version y,
si quieres borrar los datos asociados, purge_volumes (booleano).
/packages/disable Administrador
Deshabilita un paquete instalado (detiene su servicio). Envía repo y
name.
/packages/enable Administrador
Vuelve a habilitar un paquete deshabilitado (arranca su servicio). Envía repo y
name.
/packages/purge-volumes Administrador
Borra todos los volúmenes de datos de un paquete instalado. Envía repo y
name.
/packages/uninstalled-volumes Administrador
Comprueba si un paquete tiene volúmenes sobrantes de una instalación anterior. Envía
repo y name. Devuelve has_uninstalled_volumes,
uninstalled_versions e installed_versions.
/packages/purge-uninstalled-volumes Administrador
Borra los volúmenes que quedaron de versiones desinstaladas anteriormente. Envía
repo y name.
/packages/upgrades Autenticado
Lista las actualizaciones disponibles de los paquetes instalados. Cada entrada incluye
installed_version, latest_version y si la definición del paquete
ha changed.
/packages/upgrades/dismiss Administrador Descarta las notificaciones de actualización actuales. Envía un objeto JSON vacío.
/packages/manifest Autenticado
Devuelve la definición YAML en bruto del paquete. Envía repo, name
y version. Devuelve el contenido del fichero con
Content-Type: text/x-yaml. Devuelve 404 si el fichero del paquete no existe.
/packages/featured Autenticado Lista los paquetes destacados de todos los repositorios.
/packages/last-responses Autenticado
Recupera las últimas respuestas en caché de un paquete. Envía repo y
name. Devuelve las respuestas guardadas de una desinstalación previa, para
reutilizarlas al reinstalar.
/packages/clear-last-responses Administrador
Borra el fichero de últimas respuestas en caché de un paquete. Envía repo y
name.
/packages/rebuild-git Administrador
Trae los últimos cambios de los volúmenes inicializados por git de un paquete instalado y
reinicia el servicio que depende de ellos. Envía repo, name y
version. Las variables de plantilla se vuelven a evaluar con las respuestas
guardadas antes de recompilar.
Systemd
/systemd/units Autenticado
/
Localhost Lista las unidades de systemd que gestiona Town OS. Cada entrada incluye el nombre de la unidad, la descripción, los estados load/active/sub, el identificador y la descripción del paquete asociado, y un indicador de fallo. Admite parámetros de paginación.
/systemd/units-tree Autenticado
/
Localhost
Las mismas unidades que el listado plano, pero agrupadas en un árbol de dependencias: los
paquetes raíz arriba y las dependencias anidadas bajo su padre, hasta abajo — la misma
forma que usa /storage/package-volumes. Las filas llevan los mismos datos de
estado que devuelve el extremo plano, así que un cliente no necesita una segunda petición
para enriquecerlas.
/systemd/status Administrador
Controla una unidad de systemd. Envía name (el nombre de la unidad) y
action (start, stop, restart,
enable o disable).
/systemd/status/tree Administrador
Aplica una acción a un paquete y a todo su árbol de dependencias en una sola llamada, en
orden de dependencia. Aquí se rechazan enable y disable por la
misma razón que en /systemd/status: encadenar un enable habilitaría dos veces
las dependencias que ya están enlazadas a través de su padre.
/systemd/logs Administrador
/
Localhost
Transmite las entradas del journal de una unidad en tiempo real mediante Server-Sent Events.
Pasa el parámetro de consulta unit; si va vacío o vale __system__,
devuelve los registros de todo el sistema. Cada evento SSE contiene una entrada del journal
codificada en JSON, con campos como Message, Priority,
RealtimeTimestamp y SystemdUnit.
/systemd/logs/tail Administrador
/
Localhost Trae una página de entradas del journal, con paginación basada en cursores y filtrado.
| Parámetro | Tipo | Descripción |
|---|---|---|
unit | string | Nombre de la unidad de systemd. Vacío o __system__ para los registros de todo el sistema. |
lines | int | Cantidad de entradas que devolver (100 por omisión). |
before | string | Cursor — devuelve las entradas anteriores a esa posición. |
after | string | Cursor — devuelve las entradas posteriores a esa posición. |
grep | string | Filtro de subcadena sobre el texto del mensaje, sin distinguir mayúsculas. |
since | int | Marca de tiempo Unix — devuelve las entradas desde ese momento en adelante. |
until | int | Marca de tiempo Unix — deja de recolectar en ese momento. |
priority | int | Filtro por severidad de syslog (0 = sin filtro). |
Devuelve entries, cursor (la primera entrada) y
end_cursor (la última) para seguir paginando.
/systemd/logs/tree Administrador
/
Localhost
El equivalente en árbol de /systemd/logs: un solo flujo de Server-Sent Events
con el registro de un paquete y de todas las unidades por debajo de él, entremezclados en
orden cronológico. Una raíz desconocida sin registro de instalación recibe igualmente un
flujo abierto y sin entradas en lugar de un 404, así que el visor de registros funciona
igual para una unidad suelta y para todo un árbol.
/systemd/logs/tree/tail Administrador
/
Localhost
La forma paginada del registro entremezclado del árbol, que toma los mismos parámetros de
cursor, filtro y rango de tiempo que /systemd/logs/tail.
Ajustes
/settings Administrador Obtiene todos los ajustes como un objeto de clave y valor.
/settings/get Administrador
Obtiene un solo ajuste. Cuerpo de la petición:
{"key": "default_quota"}. Devuelve key y
value.
/settings/set Administrador
Establece el valor de un ajuste. Cuerpo de la petición:
{"key": "default_quota", "value": "107374182400"}.
Ajustes predeterminados
| Clave | Por omisión | Descripción |
|---|---|---|
default_quota | 53687091200 (50 GB) | Cuota predeterminada de los sistemas de ficheros nuevos. |
max_archive_size | 1073741824 (1 GB) | Tamaño máximo de fichero comprimido que se puede subir. |
archive_unpack_timeout | 600 (segundos) | Tiempo máximo para descomprimir un fichero. |
locale | en-US | Idioma de todo el sistema para la internacionalización. |
proton_image | quay.io/town/proton:latest | Imagen de contenedor del ejecutor de Proton/Wine. |
dns_tld | home | Dominio de nivel superior para la resolución DNS local. |
Registro de auditoría
/audit/log Administrador Lista las entradas del registro de auditoría. Todos los campos del cuerpo son opcionales.
| Campo | Tipo | Descripción |
|---|---|---|
before_id | int | Paginación por conjunto de claves — devuelve las entradas con ID menor a este. |
account | string | Filtrar por el usuario de la cuenta. |
sort_by | string | Campo por el que ordenar. |
sort_order | string | asc o desc. |
limit | int | Tamaño de página. |
offset | int | Desplazamiento de paginación. |
search | string | Filtro de búsqueda. |
Cada entrada de auditoría contiene id, account,
action, path, detail, success,
error y created_at. Entre las acciones auditadas están:
autenticarse, crear/actualizar/deshabilitar una cuenta, revocar una sesión,
instalar/desinstalar/deshabilitar/habilitar un paquete, crear/modificar/eliminar un sistema
de ficheros, añadir/eliminar/mover/actualizar un repositorio, subir/descargar un fichero
comprimido, actualizar un ajuste, descartar actualizaciones y purgar volúmenes.
Páginas
Alojamiento de sitios estáticos con tres tipos de origen de contenido: subir un fichero comprimido, imágenes de contenedor y repositorios git. Los usuarios asignan un dominio y el sistema sirve el contenido desde un contenedor de Caddy. Todos los endpoints que modifican algo requieren autenticación de administrador; el de listado requiere autenticación normal.
/pages Autenticado Lista todas las páginas, con ordenación, búsqueda y paginación. Se puede ordenar por nombre, URL del repositorio, rama, dominio, tipo de origen, estado y marcas de tiempo.
/pages/create Administrador
Crea una página nueva. Acepta el nombre, el tipo de origen (archive,
container_image o git), la URL del repositorio, la rama, el
dominio, la imagen de contenedor y el directorio dentro de la imagen. El tipo de origen es
archive por omisión. Las páginas de git y de imagen de contenedor se
aprovisionan de forma asíncrona.
/pages/upload Administrador
Sube un fichero tar con el contenido de una página de tipo fichero. Acepta un formulario
multiparte con name y el fichero archive. Solo es válido para
páginas con tipo de origen archive; para otros tipos devuelve 400.
/pages/update Administrador Actualización parcial de la URL del repositorio, la rama, el dominio, el tipo de origen, la imagen de contenedor o el directorio de la imagen de una página. Solo se cambian los campos que envíes.
/pages/remove Administrador Borra una página de la base de datos, quita el enlace simbólico del webroot y elimina el subvolumen btrfs.
/pages/rebuild Administrador
Recompila el contenido de una página desde su origen. Las páginas de git traen los últimos
cambios; las de imagen de contenedor vuelven a extraer desde la imagen. Las páginas de
fichero devuelven 400 (vuelve a subirlo con /pages/upload).
Redes
Una red es una superposición WireGuard con nombre, emparejada con un TLD de DNS. Los paquetes se instalan en una red, los pares se unen a ella y el TLD es lo que divide quién puede resolver qué. Los nombres de red son seguros como etiqueta DNS y están limitados a 32 caracteres, porque se reutilizan como sufijos de interfaz WireGuard y como nombres de unidad de systemd.
La red home siempre existe — se siembra junto con la propia base de datos, no
se crea al arrancar — y es especial de tres maneras: no se puede eliminar
ni crear una segunda vez, es solo de DNS (sin interfaz WireGuard, sin
subred, sin pares), y el enrolamiento de pares en ella se rechaza con un
400. Toda cuenta pertenece a la red home, así que aceptar el enrolamiento ahí haría que la
mera pertenencia fuera una forma de entrar en un túnel — y el par guardado describiría un
túnel que no existe.
Deshabilitar una red tira abajo únicamente el transporte: la interfaz WireGuard no se levanta, lo que corta el acceso remoto, mientras la resolución DNS local y los contenedores siguen ejecutándose.
/networks Autenticado Lista las redes. Cada entrada lleva el nombre, el TLD, la subred, la dirección del propio ordenador en la superposición, la clave pública, el puerto de escucha y el indicador de habilitación. La clave privada nunca se serializa.
/networks/create Administrador
Crea una red. La subred se deriva de forma determinista de una semilla de identidad del
ordenador y del nombre de la red, tomada de 10.64.0.0/10 para no chocar con
los rangos que reparten los routers domésticos. Derivarla de la identidad del ordenador
hace que dos ordenadores Town OS que sirvan pares elijan subredes distintas, así que un
dispositivo que se une a los dos nunca ve una colisión. Crear home devuelve
409 por la comprobación de colisión de TLD.
/networks/remove Administrador
Elimina una red. Rechaza la red home.
/networks/enable Administrador Levanta el transporte WireGuard de la red.
/networks/disable Administrador Tira abajo el transporte dejando el DNS y los contenedores en marcha.
Pares
/networks/peers Autenticado Lista los pares enrolados en una red.
/networks/peers/connected Administrador Lista los pares conectados en este momento, a diferencia de los que solo están enrolados.
/networks/peers/add Concesión
Enrola un par. La concesión de wireguard es lo que deja pasar a quien no es administrador;
el ámbito por red y la pertenencia de cada par los aplica el manejador. Devuelve 400 para
la red home, que es solo de DNS.
/networks/peers/refresh Concesión Renueva el enrolamiento de un par antes de que caduque su TTL. Los enrolamientos tienen vigencia y un recolector retira los que vencen.
/networks/peers/remove Administrador Retira un par de una red.
La autoridad certificadora local
/tls/ca.crt Público Descarga en formato PEM la autoridad certificadora local del ordenador. Town OS emite sus propios certificados para los nombres de los paquetes, así que confiar en este certificado es lo que hace que esos nombres funcionen en un navegador sin advertencias. Es público a propósito: un certificado de CA es justo la parte que se reparte, y un cliente lo necesita antes de tener cualquier credencial con la que autenticarse.
Almacenamiento de objetos
Town OS incorpora almacenamiento de objetos mediante gfeh. Una
partición es un subvolumen btrfs, un proceso gfehd, un socket
de administración y su propio conjunto de usuarios. Hay exactamente una
partición por red de Town OS, así que el espacio de nombres del almacenamiento de objetos
se divide por la misma frontera que divide el DNS y WireGuard: un principal, una concesión
o una exposición en la partición office no significan nada en
home.
Cada partición sirve cuatro vistas HTTP en puertos de contenedor fijos — S3 en el 9000, HTTP en el 9001, unidad en el 9002 e IPFS en el 9003 — y no publica ningún puerto del anfitrión. Eso es justo lo que vuelve seguros los puertos fijos: cada partición tiene su propio espacio de nombres de red y el ingress llega a ella por el nombre del contenedor, igual que llega a un paquete, así que dos particiones sirviendo S3 en el 9000 no pueden colisionar.
Particiones
Estas cuatro rutas existen aparte de /storage/* porque
/storage/create reescribe todo nombre que se le envía a
user/<nombre> sin excepción, y por eso no puede producir un volumen bajo
el prefijo gfeh/. Sus formas en el cable son un contrato publicado que el
cliente de gfeh interpreta, no un detalle interno.
Hay dos detalles que sostienen peso. El prefijo es asimétrico: las
peticiones llevan el nombre escueto y las respuestas llevan
gfeh/<nombre>, porque el prefijo es un artefacto del espacio de nombres
de Town OS y no parte de la identidad de la partición. Y el listado devuelve un
array JSON escueto, no un sobre paginado, a diferencia de todos los demás extremos
de listado de esta API: el cliente de gfeh deserializa una lista simple directamente y una
envoltura de paginación no se puede decodificar.
| Ruta | Autorización | Petición | Respuesta |
|---|---|---|---|
POST /gfeh/partitions/create | Administrador | name (sin prefijo), quota | Filesystem, nombre gfeh/<n> |
POST /gfeh/partitions/modify | Administrador | name, quota | Filesystem |
POST /gfeh/partitions/remove | Administrador | name | 200, vacío |
POST /gfeh/partitions | Autenticado | sin cuerpo | array simple de Filesystem |
Códigos de estado sobre los que un cliente debe ramificar: 409 ya existe
(el aprovisionamiento de gfeh es un crear-o-redimensionar y distingue ambos casos por este
estado), 404 no existe, 400 nombre inválido,
403 no es administrador. Un nombre que lleva un separador de rutas se
rechaza aquí porque gfehd lo rechaza en su propia frontera — no ponerse de
acuerdo sobre qué es un nombre de partición legal dejaría que un nombre como
../user/algo apuntara a un volumen fuera de la raíz del almacenamiento de
objetos.
Crear una partición es solo de administrador y no se alcanza con una concesión: es la raíz de un árbol de permisos y reserva un subvolumen btrfs con cuota, así que a una cuenta con concesión se le niega antes de que se ejecute ningún manejador.
Exploración
/gfeh Autenticado El panorama del almacenamiento de objetos: qué particiones existen y en qué estado están.
Principales
Los usuarios de una partición. Crear uno toma un nombre, un padre y un techo — y
ninguna contraseña, que es la razón por la que la interfaz nunca la pide.
El techo sigue la regla de proyección de gfeh: all para un administrador de
Town OS, lectura/escritura en los demás casos.
/gfeh/principals Autenticado Lista los principales de una partición.
/gfeh/principals/add Concesión Crea un principal bajo un padre, con un techo.
/gfeh/principals/remove Concesión Elimina un principal.
Concesiones
Las listas de control de acceso. gfehd recorta la concesión al techo
del principal, así que un cliente debe mostrar los permisos que
han vuelto y no los que envió: un administrador tiene que poder ver que una
concesión se ha estrechado.
/gfeh/grants Autenticado Lista las concesiones, opcionalmente las de un solo principal.
/gfeh/grants/add Concesión Da acceso a un principal. La respuesta lleva los permisos tal como han quedado guardados.
/gfeh/grants/revoke Concesión Revoca una concesión por id.
Exposiciones
Un enlace de fichero publicado, servido en /f/<token>.
/gfeh/exposures Autenticado Lista los enlaces publicados de una partición.
/gfeh/exposures/withdraw Concesión Retira un enlace publicado por su token, para que la URL deje de resolver.
DNS
Resolutor DNS local integrado, impulsado por un contenedor rolodex-dns.
Gestiona los ficheros de zona y los registros de los paquetes instalados, y ofrece
resolución de nombres local a través de una interfaz gRPC sobre socket Unix.
/dns/status Autenticado Devuelve el estado del DNS, incluyendo si está habilitado, si está en marcha, el TLD y el número de registros.
/dns/records Autenticado Lista todos los registros DNS.
/dns/records/add Administrador Añade un registro DNS. Acepta el nombre, el tipo de registro, el valor y el TTL.
/dns/records/remove Administrador Elimina un registro DNS por nombre y tipo.
/dns/tld Autenticado Obtiene el ajuste actual del dominio de nivel superior.
/dns/tld Administrador Establece el TLD. Cambia el TLD existente y vuelve a registrar todos los paquetes instalados.
/dns/setup Administrador Inicializa o reinicia el servidor DNS y registra todos los paquetes instalados.
Listas de bloqueo
Son dos listas independientes. La DNSBL se basa en suscripciones — listas de bloqueo externas que rolodex descarga y aplica — con una lista de permitidos que exime a los nombres que quieres que se resuelvan sin importar lo que diga una lista externa. La lista de bloqueo local (RBL) es la lista propia del ordenador, que se edita entrada por entrada.
/dns/dnsbl Autenticado Obtiene la configuración de DNSBL: a qué listas de bloqueo externas se está suscrito y cómo se aplican.
/dns/dnsbl Administrador Sustituye la configuración de DNSBL.
/dns/dnsbl/allowlist Autenticado Lista los nombres eximidos de las listas de bloqueo suscritas.
/dns/dnsbl/allowlist/add Administrador Exime un nombre de las listas de bloqueo suscritas.
/dns/dnsbl/allowlist/remove Administrador Quita una entrada de la lista de permitidos, dejando que las listas suscritas vuelvan a aplicarse a ese nombre.
/dns/rbl/local Autenticado Lista las entradas de la lista de bloqueo propia del ordenador.
/dns/rbl/local/add Administrador Añade un nombre a la lista de bloqueo local.
/dns/rbl/local/remove Administrador Quita un nombre de la lista de bloqueo local.
Publicación de servicios en DNS
/dns/services Autenticado Lista los servicios instalados junto con si cada uno publica o no un nombre en DNS.
/dns/services/set Administrador Activa o desactiva la publicación en DNS de un servicio, para que un paquete pueda ejecutarse sin reclamar un nombre en la red.
Monitorización
Conjunto integrado de Prometheus, Node Exporter y Grafana para la monitorización del
sistema. Todo se ejecuta como contenedores de podman supervisados por systemd con
Restart=always.
/monitoring/status Autenticado
Devuelve el estado del contenedor (nombre, imagen, si está en marcha, puerto) de cada
servicio de monitorización. Devuelve {"status": "disabled"}
cuando la monitorización no está configurada.
Cómo se llega a los datos del panel
No hay ningún proxy inverso a través del controlador del sistema. Los
datos de monitorización se sirven en su propio puerto dedicado, el 5308, y
el navegador habla directamente con ese puerto; el puerto del controlador (5309) solo lleva
/monitoring/status. Lo que escucha en el 5308 depende del backend configurado:
- Modo uPlot (el predeterminado) — un reenviador socat expone la API HTTP
de Prometheus en el 5308, y la interfaz consulta
/api/v1/query_rangedirectamente y dibuja las gráficas ella misma. - Modo Grafana — Grafana escucha directamente en el 5308 mediante una asignación de puertos de podman, y la interfaz lo incrusta en un iframe.
TOWN_OS_MONITORING_PORT reubica el puerto del panel;
TOWN_OS_PROMETHEUS_PORT y TOWN_OS_NODE_EXPORTER_PORT hacen lo
mismo con los dos puertos de loopback.
Servicios del sistema
Los servicios del sistema son contenedores de infraestructura gestionados por systemd
(distintos de los servicios de los paquetes que instala el usuario). Usan el prefijo de
nombre de unidad town-os-system--.
/system-services Público
/
Autenticado Lista los servicios del sistema con el estado de sus unidades en vivo. Accesible desde el propio equipo sin autenticación. Cada entrada incluye la clave, el nombre visible, la imagen, el puerto y los campos de estado de la unidad de systemd.
/system-services/status Administrador
Controla un servicio del sistema. Acepta key y action
(start, stop o restart).
/system-services/refresh Administrador Actualiza los ficheros de unidad y el estado de los servicios del sistema.
Idiomas
Información de idiomas del sistema para la internacionalización.
/locales Autenticado Devuelve el idioma actual, la lista de idiomas ya poblados, los idiomas comunes (con sus nombres en su propia escritura) y los idiomas extendidos. Usa códigos de idioma BCP 47.
Imágenes de máquina virtual
Gestión de las imágenes de disco en caché que usan los paquetes de máquina virtual. Las
imágenes remotas se descargan y se convierten a formato raw con
qemu-img convert; la imagen convertida queda en caché en el subvolumen
vm-images.
/vm-images Autenticado Lista las imágenes de disco de máquina virtual en caché. Devuelve el nombre y el tamaño de fichero de cada una.
/vm-images/upload Administrador
Descarga una imagen de máquina virtual desde una URL y la convierte a formato raw. Acepta
una URL y un nombre opcional. Por omisión, el nombre es el del fichero de la URL con
extensión .raw. Las descargas tienen un límite de 30 minutos.
/vm-images/delete Administrador Elimina por nombre una imagen de máquina virtual en caché.
API de administración del almacenamiento de objetos (gfeh)
Todo lo anterior es la API de Town OS, que es la que normalmente debe usar una aplicación.
Por debajo de ella, cada partición de gfehd tiene su propia superficie
administrativa: JSON sobre HTTP en únicamente su socket Unix, nunca en un
puerto.
En esta superficie no hay token ni autenticación. Los permisos del sistema
de ficheros sobre el socket son el control de acceso, así que poder llegar a él ya
significa ser root en el ordenador. El socket vive en el volumen btrfs porque es el único
sistema de ficheros que ven a la vez el contenedor de gfehd y el del
controlador del sistema.
| Llamada | Método y ruta | Para qué sirve |
|---|---|---|
Health | GET /v1/health | Señal de vida, y también la sonda de disponibilidad. |
Names | GET /v1/names | Los nombres que esta partición quiere publicar. |
ListPrincipals | GET /v1/principals | El bosque de usuarios de la partición. |
CreatePrincipal | POST /v1/principals | Toma name, parent, ceiling — y ninguna contraseña. |
DeletePrincipal | DELETE /v1/principals/<name> | Retira un principal. |
ListGrants | GET /v1/grants?principal= | Las ACL, opcionalmente de un principal. |
CreateGrant | POST /v1/grants | Da acceso; se recorta al techo del principal. |
RevokeGrant | DELETE /v1/grants/<id> | Revoca una concesión. |
ListExposures | GET /v1/exposures | Enlaces publicados en /f/<token>. |
WithdrawExposure | DELETE /v1/exposures/<token> | Deja de servir un enlace publicado. |
gfehd asigna sus errores internos a códigos de estado HTTP — 404, 409, 400 — y
el cliente de Go los asigna de vuelta a errores centinela, así que errors.Is
funciona al otro lado del socket.
Dónde viven los ficheros de una partición, para una red llamada <network>:
| Cosa | Ubicación |
|---|---|
| Datos de la partición | <btrfsBase>/gfeh/<network>, montado en /data/<network> |
| Configuración | <btrfsBase>/gfeh-control/<network>/gfehd.yaml |
| Socket de administración | <btrfsBase>/gfeh-control/<network>/run/admin.sock |
| Unidad | town-os-system--gfeh-<network>.service |
API gRPC de DNS (rolodex)
Los extremos /dns/* anteriores son la vista de DNS que da Town OS. Rolodex en
sí se gestiona por gRPC, expuesto en un socket Unix
(/var/run/rolodex-dns.sock por omisión) y opcionalmente en TCP. De serie el
socket es la única vía de gestión: grpc.tcp_bind viene vacío.
Hay un solo servicio, rolodex_dns.RolodexDnsService, con 74 métodos. Toda ruta
es /rolodex_dns.RolodexDnsService/<Método>. Las definiciones completas de
los mensajes están en proto/rolodex_dns.proto del repositorio rolodex-dns; las
agrupaciones de abajo son lo que esos métodos cubren.
Registros y resolución
| Método | Para qué sirve |
|---|---|
AddRecord | Añade un registro DNS a la base local. |
RemoveRecord | Retira registros de la base local. |
ListRecords | Consulta la base local con filtros opcionales. |
SetForwarders | Configura los reenviadores externos. |
SetResolutionMode / GetResolutionMode | Cambia y lee el modo de resolución en caliente. |
GetSearchDomains | Los dominios de búsqueda de una IP cliente. |
FlushCache | Limpia las cachés de DNS y de listas de bloqueo. |
Zonas autoritativas
| Método | Para qué sirve |
|---|---|
AddAuthoritativeZone | Declara una zona como autoritativa. |
RemoveAuthoritativeZone | Saca una zona de la lista de autoritativas. |
ListAuthoritativeZones | Lista las zonas autoritativas. |
Ámbitos de red
Los ámbitos son la forma en que rolodex divide quién resuelve qué, y son a lo que se asignan las redes de Town OS. La asociación de una IP con un ámbito lleva un TTL y hay que refrescarla.
| Método | Para qué sirve |
|---|---|
CreateNetworkScope / DeleteNetworkScope / ListNetworkScopes | Gestiona ámbitos. Borrar uno se lleva sus registros y asociaciones. |
JoinNetwork / LeaveNetwork | Asocia una IP cliente con un ámbito, o retira la asociación. |
GetNetworkAssociations | Lee las asociaciones de IP con ámbito. |
AddScopedRecord / RemoveScopedRecord / ListScopedRecords | Registros que solo existen dentro de un ámbito. |
TLD de ámbito
Zonas propias de cada red, repartidas entre redes.
| Método | Para qué sirve |
|---|---|
AddScopeTld / RemoveScopeTld / ListScopeTlds | Registra un TLD globalmente único como propiedad de un ámbito. |
SetScopeTldForwarders / ListScopeTldForwarders | Los reenviadores pares del TLD de un ámbito. |
ListScopeTldListeners | Las escuchas DNS del ingress ligadas a los TLD de un ámbito. |
Listas de bloqueo
| Método | Para qué sirve |
|---|---|
SetDnsblConfig / GetDnsblConfig | La configuración de la lista de bloqueo por suscripción. |
AddDnsblAllowlistEntry | Exime un nombre y sus subdominios de la comprobación por nombre. |
RemoveDnsblAllowlistEntry / ListDnsblAllowlistEntries | Gestiona la lista de permitidos. |
AddLocalBlocklistEntry / RemoveLocalBlocklistEntry / ListLocalBlocklistEntries | La lista de bloqueo propia del ordenador. |
Transportes cifrados
Cada transporte tiene su par de métodos para fijar y leer. DoH sirve HTTP/2 y, cuando
enable_h3 está activado, HTTP/3 en la misma dirección, puerto y certificado.
| Método | Para qué sirve |
|---|---|
SetDotConfig / GetDotConfig | DNS sobre TLS. |
SetDohConfig / GetDohConfig | DNS sobre HTTPS, incluido HTTP/3. |
SetDoqConfig / GetDoqConfig | DNS sobre QUIC. |
SetProxyConfig / GetProxyConfig | La configuración del proxy HTTP. |
DNSSEC, DANE y ACME
| Método | Para qué sirve |
|---|---|
GenerateDnssecKey / ListDnssecKeys / DeleteDnssecKey | Material de claves DNSSEC por zona. |
GetDsRecords | Los registros DS de una zona. |
SignZone | Firma una zona con sus claves DNSSEC. |
GenerateTlsaRecord / ListTlsaRecords | Registros TLSA, generados a partir de un certificado. |
GenerateDaneRootCa | Genera un certificado de CA raíz para DANE. |
EnsureZoneCa | Asegura que una zona tenga una CA. |
RequestAcmeCert / GetAcmeStatus | Pide un certificado por ACME DNS-01 y consulta su estado. |
CreateEabCredential / RemoveEabCredential | Acuña un External Account Binding (kid más HMAC) acotado a una zona, para el newAccount de un cliente ACME. |
ListAcmeAccounts / ListAcmeCertificates | Cuentas ACME registradas y certificados emitidos. |
DHCP
| Método | Para qué sirve |
|---|---|
AddDhcpPool / RemoveDhcpPool / ListDhcpPools | Rangos de direcciones para asignar dentro de un ámbito. |
ListDhcpLeases / DeleteDhcpLease | Concesiones de dirección, borradas por dirección MAC. |
SetDhcpCertOption / RemoveDhcpCertOption / ListDhcpCertOptions | Un certificado entregado a los clientes por DHCP para un ámbito. |
Diagnóstico y ajuste
| Método | Para qué sirve |
|---|---|
GetCacheStats / FlushDnsCache | Estadísticas de caché, y limpieza de la caché de respuestas. |
GetQueryLatencyStats | Latencia de las consultas externas. |
SetTtlDriftConfig / GetTtlDriftConfig | Configuración de deriva de TTL. |
SetTrackedTlds / ListTrackedTlds | La lista de TLD vigilados detrás de las métricas por TLD, guardada y efectiva. |
SetDns64Config / GetDns64Config | Configuración de DNS64. |
Bibliotecas cliente
Town OS trae bibliotecas cliente de Go y de JavaScript que cubren la API completa. Ambos clientes lanzan errores con tipo ante respuestas distintas de 200, usando el detalle de problema del RFC 9457.
Cliente de Go
El cliente de Go vive en src/svc/systemcontroller/client.go e implementa la
interfaz Client. Admite tanto conexiones por socket Unix como por HTTP.
// Conectar por socket de dominio Unix (producción)
client := systemcontroller.InitClient("/run/town-os/systemcontroller.sock")
// Conectar por HTTP (desarrollo / pruebas)
client := systemcontroller.FromClient(http.DefaultClient, "http://localhost:5309")
Establece client.Token después de autenticarte. Todos los métodos reciben un
context.Context como primer parámetro.
Almacenamiento
| Método | Descripción |
|---|---|
CreateFilesystem(ctx, fs) | Crea un subvolumen btrfs nuevo. |
ModifyFilesystem(ctx, name, fs) | Renombra o redimensiona un sistema de ficheros. |
RemoveFilesystem(ctx, name) | Borra un sistema de ficheros por su nombre. |
ListFilesystems(ctx, prefix, state, params) | Listado paginado filtrado por prefijo de nombre y por estado ("user", "installed", "uninstalled"). |
Repositorios
| Método | Descripción |
|---|---|
AddRepository(ctx, name, rawURL, username, password) | Registra un repositorio de paquetes, con credenciales opcionales. |
RemoveRepository(ctx, name) | Elimina un repositorio por su nombre. |
MoveRepository(ctx, name, position) | Cambia la prioridad (0 = la más alta). |
RefreshRepositories(ctx) | Actualiza todos los metadatos. Devuelve un mapa de errores. |
ListRepositories(ctx, params) | Listado paginado de repositorios. |
Paquetes
| Método | Descripción |
|---|---|
ListPackages(ctx, params) | Listado paginado de los paquetes disponibles. |
ListPackagesByRepo(ctx, params) | Paquetes agrupados por repositorio. |
ListPackageVersions(ctx, name) | Versiones disponibles de un paquete. |
GetPackageQuestions(ctx, name) | Preguntas de configuración por nombre. |
GetPackageQuestionsByIdentity(ctx, repo, name, version) | Preguntas de una versión concreta. |
ListChildren(ctx, repo, name) | Nombres de los paquetes hijos. |
InstallPreview(ctx, repo, name, version) | Vista previa de volúmenes y puertos sin instalar. |
InstallPackage(ctx, name, version, responses, reuseVolumes, importFromVersion, skipResponseReuse) | Instala un paquete. El nombre usa el formato "repo/paquete". |
UninstallPackage(ctx, repo, name, version, purgeVolumes) | Elimina un paquete instalado. |
DisablePackage(ctx, repo, name) | Detiene los servicios sin desinstalar. |
EnablePackage(ctx, repo, name) | Vuelve a habilitar un paquete deshabilitado. |
PurgeVolumes(ctx, repo, name) | Borra todos los volúmenes de datos de un paquete. |
ListUninstalledVolumes(ctx, repo, name) | Comprueba si hay volúmenes sobrantes. |
PurgeUninstalledVolumes(ctx, repo, name) | Borra los volúmenes sobrantes. |
ListInstalled(ctx, params) | Paquetes instalados como "repo/nombre@versión". |
GetResponses(ctx, repo, name, version) | Respuestas de configuración guardadas. |
GetInstalledInfo(ctx, repo, name, version) | Información detallada, con preguntas, respuestas y notas. |
Systemd
| Método | Descripción |
|---|---|
ListUnits(ctx, params) | Listado paginado de unidades de systemd. |
SetUnitStatus(ctx, name, action) | Aplica "start", "stop" o "restart". |
LogReplay(ctx, name) | Transmite entradas del journal por SSE. Devuelve un canal. |
LogTail(ctx, params) | Página de entradas del journal con paginación por cursor, grep, rango de tiempo y filtro de prioridad. |
Cuentas
| Método | Descripción |
|---|---|
Authenticate(ctx, username, password) | Devuelve el token de sesión y la cuenta. |
CreateAccount(ctx, username, password, email, phone, realName, admin) | Crea un usuario. Contraseña de mínimo 8 caracteres. |
GetAccount(ctx, username) | Obtiene una cuenta por su usuario. |
UpdateAccount(ctx, username, fields) | Modifica campos de la cuenta (password, email, phone, real_name, admin). |
ListAccounts(ctx, params) | Listado paginado de cuentas. |
DisableAccount(ctx, username) | Impide la autenticación. |
EnableAccount(ctx, username) | Vuelve a habilitar una cuenta deshabilitada. |
ListSessions(ctx, token) | Sesiones activas del usuario dueño del token. |
SessionUsername(ctx, token) | Usuario asociado a un token de sesión. |
RevokeSession(ctx, sessionID) | Invalida una sesión. |
Auditoría, ajustes y actualizaciones
| Método | Descripción |
|---|---|
ListAuditLog(ctx, opts, token) | Registro de auditoría paginado con filtros. |
GetSettings(ctx) | Todos los ajustes como mapa de clave y valor. |
GetSetting(ctx, key) | Un solo ajuste por su clave. |
SetSetting(ctx, key, value) | Actualiza un ajuste. |
ListUpgrades(ctx) | Paquetes con versiones más nuevas disponibles. |
DismissUpgrades(ctx) | Marca como descartadas las actualizaciones pendientes. |
Ficheros comprimidos
| Método | Descripción |
|---|---|
UploadArchive(ctx, subvolume, archiveReader, filename, subpath, stopService) | Sube y extrae un fichero comprimido dentro de un subvolumen. Formatos: tar.gz, tar.bz2, tar.xz. |
DownloadArchive(ctx, subvolume, paths, stopService, format) | Crea un fichero comprimido con el contenido de un subvolumen. Devuelve un io.ReadCloser. |
Salud
| Método | Descripción |
|---|---|
Ping(ctx) | Salud del servicio y recuentos de resumen. |
Cliente de JavaScript
El cliente de JavaScript vive en ui/src/api/ y lo usa el panel de Town OS. Está
construido como un conjunto modular de mixins sobre la clase
SystemControllerClient. Las respuestas distintas de 200 lanzan
ApiError con el detalle de problema RFC 9457 ya interpretado.
import SystemControllerClient from './api/client.js';
const client = new SystemControllerClient('http://localhost:5309');
// Después de autenticarse
const result = await client.authenticate('admin', 'password');
client.setToken(result.token); Almacenamiento
| Método | Descripción |
|---|---|
createFilesystem(fs) | Crea un subvolumen btrfs nuevo. |
modifyFilesystem(name, fs) | Renombra o redimensiona un sistema de ficheros. |
removeFilesystem(name) | Borra un sistema de ficheros por su nombre. |
listFilesystems(prefix, sortBy, sortOrder, state, limit, offset, search) | Listado paginado con filtros. |
Repositorios
| Método | Descripción |
|---|---|
addRepository(name, url, username?, password?) | Registra un repositorio, con credenciales opcionales. |
removeRepository(name) | Elimina un repositorio por su nombre. |
moveRepository(name, position) | Cambia la prioridad (0 = la más alta). |
refreshRepositories() | Actualiza todos los metadatos. Devuelve un mapa de errores o null. |
listRepositories(sortBy, sortOrder, limit, offset, search) | Listado paginado. |
Paquetes
| Método | Descripción |
|---|---|
listPackages(sortBy, sortOrder, limit, offset, search) | Listado paginado de los paquetes disponibles. |
listPackagesByRepo(search) | Paquetes agrupados por repositorio. |
listPackageVersions(name) | Versiones disponibles de un paquete. |
getPackageQuestions(name) | Preguntas de configuración por nombre. |
getPackageQuestionsByIdentity(repo, name, version) | Preguntas de una versión concreta. |
installPreview(repo, name, version) | Vista previa de volúmenes y puertos sin instalar. |
installPackage(repo, name, version, responses, reuseVolumes?, importFromVersion?) | Instala un paquete con las respuestas de configuración. |
uninstallPackage(repo, name, version, purgeVolumes?) | Elimina un paquete instalado. |
disablePackage(repo, name) | Detiene los servicios sin desinstalar. |
enablePackage(repo, name) | Vuelve a habilitar un paquete deshabilitado. |
purgeVolumes(repo, name) | Borra todos los volúmenes de datos de un paquete. |
listUninstalledVolumes(repo, name) | Comprueba si hay volúmenes sobrantes. |
purgeUninstalledVolumes(repo, name) | Borra los volúmenes sobrantes. |
listInstalled(sortBy, sortOrder, limit, offset, search) | Paquetes instalados como "repo/nombre@versión". |
getResponses(repo, name, version) | Respuestas de configuración guardadas. |
getInstalledInfo(repo, name, version) | Información detallada, con preguntas, respuestas y notas. |
Systemd
| Método | Descripción |
|---|---|
listUnits(sortBy, sortOrder, limit, offset, search) | Listado paginado de unidades de systemd. |
setUnitStatus(name, action) | Aplica "start", "stop" o "restart". |
logReplay(unit) | Transmite entradas del journal por SSE. Devuelve un AsyncGenerator. |
logTail(unit, lines?, before?, after?, grep?, since?, until?, priority?) | Página de entradas del journal con paginación por cursor, grep, rango de tiempo y filtro de prioridad. |
Cuentas
| Método | Descripción |
|---|---|
authenticate(username, password) | Devuelve el token de sesión y la cuenta. |
createAccount(username, password, email, phone, realName, admin) | Crea un usuario. Contraseña de mínimo 8 caracteres. |
getAccount(username) | Obtiene una cuenta por su usuario. |
updateAccount(username, fields) | Modifica campos de la cuenta. |
listAccounts(sortBy, sortOrder, limit, offset, search) | Listado paginado de cuentas. |
disableAccount(username) | Impide la autenticación. |
enableAccount(username) | Vuelve a habilitar una cuenta deshabilitada. |
listSessions(token) | Sesiones activas del usuario dueño del token. |
sessionUsername(token) | Usuario asociado a un token de sesión. |
revokeSession(sessionID) | Invalida una sesión. |
Auditoría, ajustes y actualizaciones
| Método | Descripción |
|---|---|
listAuditLog(opts) | Registro de auditoría paginado con filtros. |
getSettings() | Todos los ajustes como objeto de clave y valor. |
getSetting(key) | Un solo ajuste por su clave. |
setSetting(key, value) | Actualiza un ajuste. |
listUpgrades() | Paquetes con versiones más nuevas disponibles. |
dismissUpgrades() | Marca como descartadas las actualizaciones pendientes. |
Ficheros comprimidos
| Método | Descripción |
|---|---|
uploadArchive(subvolume, file, subpath?, stopService?) | Sube y extrae un fichero comprimido con FormData. Devuelve {needs_restart, message}. |
downloadArchive(subvolume, paths?, stopService?, format?) | Descarga un fichero comprimido del subvolumen. Devuelve la Response en bruto para transmitirla. |
Salud
| Método | Descripción |
|---|---|
ping() | Salud del servicio y recuentos de resumen. |
Referencia de desarrollo
El backend de Town OS se ejecuta en el puerto 5309, con un servidor de desarrollo de Vite en
el 5173. Usa make dev para levantar todo el entorno de desarrollo.
Objetivos principales
| Objetivo | Descripción |
|---|---|
make dev | Levanta todo el entorno de desarrollo (backend + servidor de Vite). |
make dev-stop | Detiene y elimina el contenedor del backend de desarrollo. |
make dev-logs | Sigue journalctl dentro del contenedor de desarrollo en marcha. |
make dev-clean | Detiene el contenedor y desmonta el volumen btrfs de desarrollo. |
Objetivos de pruebas
| Objetivo | Descripción |
|---|---|
make test | Lanza el análisis estático y las pruebas unitarias de Go y de JS. |
make test-integration | Lanza las pruebas de integración de Go en un contenedor de Podman con privilegios. |
make test-ui-integration | Lanza las pruebas de integración de la interfaz con Bun contra un contenedor del backend. |
make test-full | Lanza todas las baterías de pruebas en orden. |
make auto-test | Vigila los cambios de ficheros y vuelve a lanzar las pruebas solo. |
Objetivos de compilación
| Objetivo | Descripción |
|---|---|
make production-image | Compila la imagen de contenedor de producción. |
make test-image | Compila la imagen de contenedor de pruebas. |
make pull-images | Descarga las imágenes base de contenedor desde Docker Hub. |
Requisitos previos
- Go 1.25+
- Bun — entorno de ejecución de JavaScript
- Podman — en modo rootful, con
sudo - btrfs-progs —
mkfs.btrfs - golangci-lint
Crea un fichero .env con las credenciales del repositorio:
TOWN_OS_REPO_USERNAME=<usuario>
TOWN_OS_REPO_PASSWORD=<contraseña>
Después de instalar los requisitos previos, ejecuta make pull-images antes que
cualquier otro objetivo.