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, monitoreo, servicios del sistema, idiomas, imágenes de máquina virtual y estado.
Panorama 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 específica 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 alcance 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 la computadora — y cualquier otro origen necesita el nivel que aparece junto a la insignia. Lo usan los extremos de unidades y de bitácoras 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 aparta 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 panorama 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
archivos, los conteos 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 vuelve 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. Manda 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 archivos. 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. Manda 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 archivos existente. Manda name para identificarlo y un
objeto filesystem con el name y/o la quota
actualizados.
/storage/remove Autenticado
Elimina un sistema de archivos. Cuerpo de la petición:
{"name": "mydata"}.
/storage/upload-archive Administrador
Sube y descomprime un archivo dentro de un subvolumen de destino. Acepta
multipart/form-data con un campo subvolume y un archivo
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. Archivo 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 archivo comprimido con el contenido de un subvolumen. Devuelve un archivo transmitido en el formato solicitado.
| Campo | Tipo | Descripción |
|---|---|---|
subvolume | string | Obligatorio. Ruta del subvolumen de origen. |
paths | string[] | Opcional. Arreglo 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 archivo descargado. El servidor le agrega 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 de una sola llamada todos los volúmenes que pertenecen a un paquete, en lugar de quitarlos uno por 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 Agrega 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 le ganan a 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 mapea 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 arreglo 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. Manda 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. Manda 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 arreglo de cadenas con los
identificadores de versión.
/packages/children Autenticado
Lista los paquetes hijos. Manda repo y name. Devuelve un arreglo
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. Manda repo,
name y version.
/packages/oauth/start Administrador
Inicia el flujo de dispositivo OAuth de una pregunta oauth. Manda
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 revisan 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. Manda flow_id. Devuelve status:
pending mientras el usuario no haya aprobado, approved junto con
el token, o expired una vez que el flujo caducó o su token ya se
recogió — 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. Manda 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. Manda repo, name, version y,
si quieres borrar los datos asociados, purge_volumes (booleano).
/packages/disable Administrador
Deshabilita un paquete instalado (detiene su servicio). Manda repo y
name.
/packages/enable Administrador
Vuelve a habilitar un paquete deshabilitado (arranca su servicio). Manda repo
y name.
/packages/purge-volumes Administrador
Borra todos los volúmenes de datos de un paquete instalado. Manda repo y
name.
/packages/uninstalled-volumes Administrador
Revisa si un paquete tiene volúmenes sobrantes de una instalación anterior. Manda
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. Manda
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. Manda un objeto JSON vacío.
/packages/manifest Autenticado
Devuelve la definición YAML cruda del paquete. Manda repo, name y
version. Devuelve el contenido del archivo con
Content-Type: text/x-yaml. Devuelve 404 si el archivo 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. Manda repo y
name. Devuelve las respuestas guardadas de una desinstalación previa, para
reutilizarlas al reinstalar.
/packages/clear-last-responses Administrador
Borra el archivo de últimas respuestas en caché de un paquete. Manda repo y
name.
/packages/rebuild-git Administrador
Trae los últimos cambios de los volúmenes sembrados por git de un paquete instalado y
reinicia el servicio que depende de ellos. Manda repo, name y
version. Las variables de plantilla se vuelven a evaluar con las respuestas
guardadas antes de reconstruir.
Systemd
/systemd/units Autenticado
/
Localhost Lista las unidades de systemd que administra 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 una bandera 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 traen 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. Manda 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 la bitácora de un paquete y de todas las unidades por debajo de él,
entremezcladas en orden cronológico. Una raíz desconocida sin registro de instalación
igual recibe un flujo abierto y sin entradas en lugar de un 404, así que el visor de
bitácoras funciona igual para una unidad suelta y para todo un árbol.
/systemd/logs/tree/tail Administrador
/
Localhost
La forma paginada de la bitácora entremezclada 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
Define 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 archivos nuevos. |
max_archive_size | 1073741824 (1 GB) | Tamaño máximo de archivo comprimido que se puede subir. |
archive_unpack_timeout | 600 (segundos) | Tiempo máximo para descomprimir un archivo. |
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. |
Bitácora de auditoría
/audit/log Administrador Lista las entradas de la bitácora 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 archivos, agregar/eliminar/mover/actualizar un repositorio, subir/descargar un archivo
comprimido, actualizar un ajuste, descartar actualizaciones y purgar volúmenes.
Páginas
Hospedaje de sitios estáticos con tres tipos de origen de contenido: subir un archivo 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 ordenamiento, 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 preparan
de forma asíncrona.
/pages/upload Administrador
Sube un archivo tar con el contenido de una página de tipo archivo. Acepta un formulario
multiparte con name y el archivo 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
Reconstruye 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 archivo 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 topados 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
simple membresía fuera una manera de entrar a un túnel — y el par guardado describiría un
túnel que no existe.
Deshabilitar una red baja ú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 corriendo.
/networks Autenticado Lista las redes. Cada entrada trae el nombre, el TLD, la subred, la dirección de la propia computadora en la superposición, la llave pública, el puerto de escucha y la bandera de habilitación. La llave privada nunca se serializa.
/networks/create Administrador
Crea una red. La subred se deriva de forma determinista de una semilla de identidad de la
computadora 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 de la
computadora hace que dos computadoras Town OS que sirvan pares elijan subredes distintas,
así que un dispositivo que se une a las 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 Baja el transporte dejando el DNS y los contenedores corriendo.
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 alcance 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 quita los que se vencen.
/networks/peers/remove Administrador Quita un par de una red.
La autoridad certificadora local
/tls/ca.crt Público Descarga en formato PEM la autoridad certificadora local de la computadora. 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 trae almacenamiento de objetos por medio de 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 parte por la misma frontera que parte 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 chocar.
Particiones
Estas cuatro rutas existen aparte de /storage/* porque
/storage/create reescribe todo nombre que se le manda 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 cargan peso. El prefijo es asimétrico: las peticiones
llevan el nombre pelón 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 arreglo JSON pelón, 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 | arreglo 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 los dos casos por
este estado), 404 no existe, 400 nombre inválido,
403 no es administrador. Un nombre que trae 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 aparta un subvolumen btrfs con cuota, así que a una cuenta con concesión se le niega antes de que corra 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 regresaron
y no los que mandó: un administrador tiene que poder ver que una concesión se estrechó.
/gfeh/grants Autenticado Lista las concesiones, opcionalmente las de un solo principal.
/gfeh/grants/add Concesión Le da acceso a un principal. La respuesta trae los permisos tal como quedaron guardados.
/gfeh/grants/revoke Concesión Revoca una concesión por id.
Exposiciones
Un enlace de archivo 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
Resolvedor DNS local integrado, impulsado por un contenedor rolodex-dns.
Administra los archivos 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á corriendo, el TLD y el número de registros.
/dns/records Autenticado Lista todos los registros DNS.
/dns/records/add Administrador Agrega 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 Define 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 de la computadora, 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 Reemplaza 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 de la computadora.
/dns/rbl/local/add Administrador Agrega 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 Prende o apaga la publicación en DNS de un servicio, para que un paquete pueda correr sin reclamar un nombre en la red.
Monitoreo
Conjunto integrado de Prometheus, Node Exporter y Grafana para el monitoreo del sistema.
Todo corre como contenedores de podman supervisados por systemd con
Restart=always.
/monitoring/status Autenticado
Devuelve el estado del contenedor (nombre, imagen, si está corriendo, puerto) de cada
servicio de monitoreo. Devuelve {"status": "disabled"} cuando el
monitoreo no está configurado.
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 monitoreo se sirven en su propio puerto dedicado, el 5308, y el
navegador habla directo 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 de omisión) — 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 directo en el 5308 mediante un mapeo de puertos de podman, y la interfaz lo empotra en un iframe.
TOWN_OS_MONITORING_PORT cambia de lugar 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 administrados 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 archivos 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
Administració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 archivo 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 archivo 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 de arriba 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 archivos sobre el socket son el control de acceso, así que poder llegar a él ya
significa ser root en la computadora. El socket vive en el volumen btrfs porque es el único
sistema de archivos 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> | Quita 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 mapea sus errores internos a códigos de estado HTTP — 404, 409, 400 — y
el cliente de Go los mapea de vuelta a errores centinela, así que errors.Is
funciona al otro lado del socket.
Dónde viven los archivos 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/* de arriba son la vista de DNS que da Town OS. Rolodex en
sí se administra por gRPC, expuesto en un socket Unix
(/var/run/rolodex-dns.sock por omisión) y opcionalmente en TCP. De fábrica el
socket es la única vía de administració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; los
agrupamientos de abajo son lo que esos métodos cubren.
Registros y resolución
| Método | Para qué sirve |
|---|---|
AddRecord | Agrega un registro DNS a la base local. |
RemoveRecord | Quita 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. |
Alcances de red
Los alcances son la forma en que rolodex divide quién resuelve qué, y son a lo que se mapean las redes de Town OS. La asociación de una IP con un alcance trae un TTL y hay que refrescarla.
| Método | Para qué sirve |
|---|---|
CreateNetworkScope / DeleteNetworkScope / ListNetworkScopes | Administra alcances. Borrar uno se lleva sus registros y asociaciones. |
JoinNetwork / LeaveNetwork | Asocia una IP cliente con un alcance, o quita la asociación. |
GetNetworkAssociations | Lee las asociaciones de IP con alcance. |
AddScopedRecord / RemoveScopedRecord / ListScopedRecords | Registros que solo existen dentro de un alcance. |
TLD de alcance
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 alcance. |
SetScopeTldForwarders / ListScopeTldForwarders | Los reenviadores pares del TLD de un alcance. |
ListScopeTldListeners | Las escuchas DNS del ingress ligadas a los TLD de un alcance. |
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 | Administra la lista de permitidos. |
AddLocalBlocklistEntry / RemoveLocalBlocklistEntry / ListLocalBlocklistEntries | La lista de bloqueo propia de la computadora. |
Transportes cifrados
Cada transporte tiene su par de métodos para fijar y leer. DoH sirve HTTP/2 y, cuando
enable_h3 está prendido, 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 llaves DNSSEC por zona. |
GetDsRecords | Los registros DS de una zona. |
SignZone | Firma una zona con sus llaves 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 alcance. |
ListDhcpLeases / DeleteDhcpLease | Concesiones de dirección, borradas por dirección MAC. |
SetDhcpCertOption / RemoveDhcpCertOption / ListDhcpCertOptions | Un certificado entregado a los clientes por DHCP para un alcance. |
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")
Define 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 archivos. |
RemoveFilesystem(ctx, name) | Borra un sistema de archivos 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) | Revisa 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) | Bitácora de auditoría paginada 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. |
Archivos comprimidos
| Método | Descripción |
|---|---|
UploadArchive(ctx, subvolume, archiveReader, filename, subpath, stopService) | Sube y extrae un archivo comprimido dentro de un subvolumen. Formatos: tar.gz, tar.bz2, tar.xz. |
DownloadArchive(ctx, subvolume, paths, stopService, format) | Crea un archivo comprimido con el contenido de un subvolumen. Devuelve un io.ReadCloser. |
Salud
| Método | Descripción |
|---|---|
Ping(ctx) | Salud del servicio y conteos 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 archivos. |
removeFilesystem(name) | Borra un sistema de archivos 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) | Revisa 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) | Bitácora de auditoría paginada 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. |
Archivos comprimidos
| Método | Descripción |
|---|---|
uploadArchive(subvolume, file, subpath?, stopService?) | Sube y extrae un archivo comprimido con FormData. Devuelve {needs_restart, message}. |
downloadArchive(subvolume, paths?, stopService?, format?) | Descarga un archivo comprimido del subvolumen. Devuelve la Response cruda para transmitirla. |
Salud
| Método | Descripción |
|---|---|
ping() | Salud del servicio y conteos de resumen. |
Referencia de desarrollo
El backend de Town OS corre 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 | Corre el análisis estático y las pruebas unitarias de Go y de JS. |
make test-integration | Corre las pruebas de integración de Go en un contenedor de Podman con privilegios. |
make test-ui-integration | Corre las pruebas de integración de la interfaz con Bun contra un contenedor del backend. |
make test-full | Corre todas las suites de pruebas en orden. |
make auto-test | Vigila los cambios de archivos y vuelve a correr las pruebas solo. |
Objetivos de construcción
| Objetivo | Descripción |
|---|---|
make production-image | Construye la imagen de contenedor de producción. |
make test-image | Construye 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 archivo .env con las credenciales del repositorio:
TOWN_OS_REPO_USERNAME=<usuario>
TOWN_OS_REPO_PASSWORD=<contraseña>
Después de instalar los requisitos previos, corre make pull-images antes que
cualquier otro objetivo.