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:

NivelDescripción
PúblicoNo requiere token.
AutenticadoCualquier token de sesión válido.
AdministradorToken de sesión de una cuenta de administrador.
ConcesiónUna 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.
LocalhostLas 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ámetroTipoDescripción
sort_bystringNombre del campo por el que ordenar.
sort_orderstringasc o desc.
limitintTamaño de página (20 por omisión).
offsetintDesplazamiento de paginación.
searchstringCoincidencia 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

GET /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

POST /account/authenticate Público

Autentica con usuario y contraseña. Devuelve un token de sesión y el objeto de la cuenta.

CampoTipoDescripción
usernamestringObligatorio. Usuario de la cuenta.
passwordstringObligatorio. Contraseña de la cuenta.
POST /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.

CampoTipoDescripción
usernamestringObligatorio.
passwordstringObligatorio. Mínimo 8 caracteres.
emailstringObligatorio.
phonestringObligatorio.
real_namestringObligatorio.
adminbooleanSi la cuenta tiene privilegios de administrador.
POST /account Autenticado

Obtiene una sola cuenta por su usuario. Cuerpo de la petición: {"username": "alice"}.

GET /account Autenticado

Lista todas las cuentas. Admite parámetros de paginación.

POST /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.

GET /account/me Autenticado

Devuelve el usuario asociado al token de la cabecera Authorization.

GET /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.

POST /account/session/revoke Autenticado

Revoca una sesión por su ID. Cuerpo de la petición: {"session_id": "..."}.

POST /account/disable Administrador

Deshabilita una cuenta. Cuerpo de la petición: {"username": "bob"}.

POST /account/enable Administrador

Vuelve a habilitar una cuenta deshabilitada. Cuerpo de la petición: {"username": "bob"}.

Almacenamiento

POST /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).

POST /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.

POST /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.

POST /storage/remove Autenticado

Elimina un sistema de archivos. Cuerpo de la petición: {"name": "mydata"}.

POST /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.

CampoTipoDescripción
subvolumestringObligatorio. Ruta del subvolumen de destino.
archivefileObligatorio. Archivo comprimido que se va a subir.
subpathstringOpcional. Ruta relativa dentro del volumen donde descomprimir; se crea si hace falta.
stop_servicestringOpcional. Nombre de la unidad de systemd que se detiene antes de descomprimir y se reinicia al terminar.
AjustePor omisiónDescripción
max_archive_size1 GBTamaño máximo de subida.
archive_unpack_timeout600 segundosTiempo máximo para descomprimir.
POST /storage/download-archive Administrador

Descarga un archivo comprimido con el contenido de un subvolumen. Devuelve un archivo transmitido en el formato solicitado.

CampoTipoDescripción
subvolumestringObligatorio. Ruta del subvolumen de origen.
pathsstring[]Opcional. Arreglo de rutas concretas dentro del subvolumen que se van a incluir.
stop_servicestringOpcional. Nombre de la unidad de systemd que se detiene mientras se comprime y se reinicia después.
formatstringOpcional. Formato de compresión: tar.gz (por omisión), tar.bz2 o tar.xz.
filenamestringOpcional. Nombre base personalizado para el archivo descargado. El servidor le agrega la extensión que corresponda. Por omisión, download.
POST /storage/package-volumes Autenticado

Lista los volúmenes de los paquetes agrupados por paquete, con la opción de incluir los volúmenes desinstalados.

POST /storage/remove-package-volume Administrador

Borra un volumen concreto de un paquete usando su nombre interno.

POST /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

GET /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.

POST /repository/add Autenticado

Agrega un repositorio de paquetes nuevo. Dispara una actualización inmediata.

CampoTipoDescripción
namestringObligatorio. Nombre visible del repositorio.
urlstringObligatorio. URL de git del repositorio.
usernamestringOpcional. Usuario de autenticación para repositorios privados.
passwordstringOpcional. Contraseña de autenticación para repositorios privados.
POST /repository/remove Autenticado

Elimina un repositorio por su nombre. Dispara una actualización inmediata. Cuerpo de la petición: {"name": "my-repo"}.

POST /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}.

POST /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

GET /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.

GET /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": [...]}.

GET /packages/installed Autenticado

Lista los identificadores de los paquetes instalados. Admite parámetros de paginación.

POST /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.

POST /packages/responses Autenticado

Obtiene las respuestas guardadas de un paquete instalado. Manda repo, name y version. Devuelve un mapa de clave y valor.

POST /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.

POST /packages/children Autenticado

Lista los paquetes hijos. Manda repo y name. Devuelve un arreglo de cadenas.

POST /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": "..."}.

POST /packages/questions/identity Administrador

Obtiene las preguntas de una versión concreta de un paquete. Manda repo, name y version.

POST /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.

POST /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.

POST /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.

POST /packages/install Administrador

Instala un paquete.

CampoTipoDescripción
repostringObligatorio. Nombre del repositorio.
namestringObligatorio. Nombre del paquete.
versionstringObligatorio. Versión que se va a instalar.
responsesobjectObligatorio. Respuestas de clave y valor a las preguntas de instalación.
reuse_volumesbooleanReutilizar los volúmenes de datos de una instalación anterior.
import_from_versionstringVersión desde la que importar los volúmenes al actualizar.
POST /packages/uninstall Administrador

Desinstala un paquete. Manda repo, name, version y, si quieres borrar los datos asociados, purge_volumes (booleano).

POST /packages/disable Administrador

Deshabilita un paquete instalado (detiene su servicio). Manda repo y name.

POST /packages/enable Administrador

Vuelve a habilitar un paquete deshabilitado (arranca su servicio). Manda repo y name.

POST /packages/purge-volumes Administrador

Borra todos los volúmenes de datos de un paquete instalado. Manda repo y name.

POST /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.

POST /packages/purge-uninstalled-volumes Administrador

Borra los volúmenes que quedaron de versiones desinstaladas anteriormente. Manda repo y name.

GET /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.

POST /packages/upgrades/dismiss Administrador

Descarta las notificaciones de actualización actuales. Manda un objeto JSON vacío.

POST /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.

GET /packages/featured Autenticado

Lista los paquetes destacados de todos los repositorios.

POST /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.

POST /packages/clear-last-responses Administrador

Borra el archivo de últimas respuestas en caché de un paquete. Manda repo y name.

POST /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

GET /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.

GET /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.

POST /systemd/status Administrador

Controla una unidad de systemd. Manda name (el nombre de la unidad) y action (start, stop, restart, enable o disable).

POST /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.

GET /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.

GET /systemd/logs/tail Administrador / Localhost

Trae una página de entradas del journal, con paginación basada en cursores y filtrado.

ParámetroTipoDescripción
unitstringNombre de la unidad de systemd. Vacío o __system__ para los registros de todo el sistema.
linesintCantidad de entradas que devolver (100 por omisión).
beforestringCursor — devuelve las entradas anteriores a esa posición.
afterstringCursor — devuelve las entradas posteriores a esa posición.
grepstringFiltro de subcadena sobre el texto del mensaje, sin distinguir mayúsculas.
sinceintMarca de tiempo Unix — devuelve las entradas desde ese momento en adelante.
untilintMarca de tiempo Unix — deja de recolectar en ese momento.
priorityintFiltro por severidad de syslog (0 = sin filtro).

Devuelve entries, cursor (la primera entrada) y end_cursor (la última) para seguir paginando.

GET /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.

GET /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

GET /settings Administrador

Obtiene todos los ajustes como un objeto de clave y valor.

POST /settings/get Administrador

Obtiene un solo ajuste. Cuerpo de la petición: {"key": "default_quota"}. Devuelve key y value.

POST /settings/set Administrador

Define el valor de un ajuste. Cuerpo de la petición: {"key": "default_quota", "value": "107374182400"}.

Ajustes predeterminados

ClavePor omisiónDescripción
default_quota53687091200 (50 GB)Cuota predeterminada de los sistemas de archivos nuevos.
max_archive_size1073741824 (1 GB)Tamaño máximo de archivo comprimido que se puede subir.
archive_unpack_timeout600 (segundos)Tiempo máximo para descomprimir un archivo.
localeen-USIdioma de todo el sistema para la internacionalización.
proton_imagequay.io/town/proton:latestImagen de contenedor del ejecutor de Proton/Wine.
dns_tldhomeDominio de nivel superior para la resolución DNS local.

Bitácora de auditoría

POST /audit/log Administrador

Lista las entradas de la bitácora de auditoría. Todos los campos del cuerpo son opcionales.

CampoTipoDescripción
before_idintPaginación por conjunto de claves — devuelve las entradas con ID menor a este.
accountstringFiltrar por el usuario de la cuenta.
sort_bystringCampo por el que ordenar.
sort_orderstringasc o desc.
limitintTamaño de página.
offsetintDesplazamiento de paginación.
searchstringFiltro 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.

GET /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.

POST /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.

POST /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.

POST /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.

POST /pages/remove Administrador

Borra una página de la base de datos, quita el enlace simbólico del webroot y elimina el subvolumen btrfs.

POST /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.

GET /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.

POST /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.

POST /networks/remove Administrador

Elimina una red. Rechaza la red home.

POST /networks/enable Administrador

Levanta el transporte WireGuard de la red.

POST /networks/disable Administrador

Baja el transporte dejando el DNS y los contenedores corriendo.

Pares

GET /networks/peers Autenticado

Lista los pares enrolados en una red.

GET /networks/peers/connected Administrador

Lista los pares conectados en este momento, a diferencia de los que solo están enrolados.

POST /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.

POST /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.

POST /networks/peers/remove Administrador

Quita un par de una red.

La autoridad certificadora local

GET /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.

RutaAutorizaciónPeticiónRespuesta
POST /gfeh/partitions/createAdministradorname (sin prefijo), quotaFilesystem, nombre gfeh/<n>
POST /gfeh/partitions/modifyAdministradorname, quotaFilesystem
POST /gfeh/partitions/removeAdministradorname200, vacío
POST /gfeh/partitionsAutenticadosin cuerpoarreglo 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

GET /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.

GET /gfeh/principals Autenticado

Lista los principales de una partición.

POST /gfeh/principals/add Concesión

Crea un principal bajo un padre, con un techo.

POST /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ó.

GET /gfeh/grants Autenticado

Lista las concesiones, opcionalmente las de un solo principal.

POST /gfeh/grants/add Concesión

Le da acceso a un principal. La respuesta trae los permisos tal como quedaron guardados.

POST /gfeh/grants/revoke Concesión

Revoca una concesión por id.

Exposiciones

Un enlace de archivo publicado, servido en /f/<token>.

GET /gfeh/exposures Autenticado

Lista los enlaces publicados de una partición.

POST /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.

GET /dns/status Autenticado

Devuelve el estado del DNS, incluyendo si está habilitado, si está corriendo, el TLD y el número de registros.

GET /dns/records Autenticado

Lista todos los registros DNS.

POST /dns/records/add Administrador

Agrega un registro DNS. Acepta el nombre, el tipo de registro, el valor y el TTL.

POST /dns/records/remove Administrador

Elimina un registro DNS por nombre y tipo.

GET /dns/tld Autenticado

Obtiene el ajuste actual del dominio de nivel superior.

POST /dns/tld Administrador

Define el TLD. Cambia el TLD existente y vuelve a registrar todos los paquetes instalados.

POST /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.

GET /dns/dnsbl Autenticado

Obtiene la configuración de DNSBL: a qué listas de bloqueo externas se está suscrito y cómo se aplican.

POST /dns/dnsbl Administrador

Reemplaza la configuración de DNSBL.

GET /dns/dnsbl/allowlist Autenticado

Lista los nombres eximidos de las listas de bloqueo suscritas.

POST /dns/dnsbl/allowlist/add Administrador

Exime un nombre de las listas de bloqueo suscritas.

POST /dns/dnsbl/allowlist/remove Administrador

Quita una entrada de la lista de permitidos, dejando que las listas suscritas vuelvan a aplicarse a ese nombre.

GET /dns/rbl/local Autenticado

Lista las entradas de la lista de bloqueo propia de la computadora.

POST /dns/rbl/local/add Administrador

Agrega un nombre a la lista de bloqueo local.

POST /dns/rbl/local/remove Administrador

Quita un nombre de la lista de bloqueo local.

Publicación de servicios en DNS

GET /dns/services Autenticado

Lista los servicios instalados junto con si cada uno publica o no un nombre en DNS.

POST /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.

GET /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_range directamente 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--.

GET /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.

POST /system-services/status Administrador

Controla un servicio del sistema. Acepta key y action (start, stop o restart).

POST /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.

GET /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.

GET /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.

POST /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.

POST /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.

LlamadaMétodo y rutaPara qué sirve
HealthGET /v1/healthSeñal de vida, y también la sonda de disponibilidad.
NamesGET /v1/namesLos nombres que esta partición quiere publicar.
ListPrincipalsGET /v1/principalsEl bosque de usuarios de la partición.
CreatePrincipalPOST /v1/principalsToma name, parent, ceiling — y ninguna contraseña.
DeletePrincipalDELETE /v1/principals/<name>Quita un principal.
ListGrantsGET /v1/grants?principal=Las ACL, opcionalmente de un principal.
CreateGrantPOST /v1/grantsDa acceso; se recorta al techo del principal.
RevokeGrantDELETE /v1/grants/<id>Revoca una concesión.
ListExposuresGET /v1/exposuresEnlaces publicados en /f/<token>.
WithdrawExposureDELETE /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>:

CosaUbicació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
Unidadtown-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étodoPara qué sirve
AddRecordAgrega un registro DNS a la base local.
RemoveRecordQuita registros de la base local.
ListRecordsConsulta la base local con filtros opcionales.
SetForwardersConfigura los reenviadores externos.
SetResolutionMode / GetResolutionModeCambia y lee el modo de resolución en caliente.
GetSearchDomainsLos dominios de búsqueda de una IP cliente.
FlushCacheLimpia las cachés de DNS y de listas de bloqueo.

Zonas autoritativas

MétodoPara qué sirve
AddAuthoritativeZoneDeclara una zona como autoritativa.
RemoveAuthoritativeZoneSaca una zona de la lista de autoritativas.
ListAuthoritativeZonesLista 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étodoPara qué sirve
CreateNetworkScope / DeleteNetworkScope / ListNetworkScopesAdministra alcances. Borrar uno se lleva sus registros y asociaciones.
JoinNetwork / LeaveNetworkAsocia una IP cliente con un alcance, o quita la asociación.
GetNetworkAssociationsLee las asociaciones de IP con alcance.
AddScopedRecord / RemoveScopedRecord / ListScopedRecordsRegistros que solo existen dentro de un alcance.

TLD de alcance

Zonas propias de cada red, repartidas entre redes.

MétodoPara qué sirve
AddScopeTld / RemoveScopeTld / ListScopeTldsRegistra un TLD globalmente único como propiedad de un alcance.
SetScopeTldForwarders / ListScopeTldForwardersLos reenviadores pares del TLD de un alcance.
ListScopeTldListenersLas escuchas DNS del ingress ligadas a los TLD de un alcance.

Listas de bloqueo

MétodoPara qué sirve
SetDnsblConfig / GetDnsblConfigLa configuración de la lista de bloqueo por suscripción.
AddDnsblAllowlistEntryExime un nombre y sus subdominios de la comprobación por nombre.
RemoveDnsblAllowlistEntry / ListDnsblAllowlistEntriesAdministra la lista de permitidos.
AddLocalBlocklistEntry / RemoveLocalBlocklistEntry / ListLocalBlocklistEntriesLa 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étodoPara qué sirve
SetDotConfig / GetDotConfigDNS sobre TLS.
SetDohConfig / GetDohConfigDNS sobre HTTPS, incluido HTTP/3.
SetDoqConfig / GetDoqConfigDNS sobre QUIC.
SetProxyConfig / GetProxyConfigLa configuración del proxy HTTP.

DNSSEC, DANE y ACME

MétodoPara qué sirve
GenerateDnssecKey / ListDnssecKeys / DeleteDnssecKeyMaterial de llaves DNSSEC por zona.
GetDsRecordsLos registros DS de una zona.
SignZoneFirma una zona con sus llaves DNSSEC.
GenerateTlsaRecord / ListTlsaRecordsRegistros TLSA, generados a partir de un certificado.
GenerateDaneRootCaGenera un certificado de CA raíz para DANE.
EnsureZoneCaAsegura que una zona tenga una CA.
RequestAcmeCert / GetAcmeStatusPide un certificado por ACME DNS-01 y consulta su estado.
CreateEabCredential / RemoveEabCredentialAcuña un External Account Binding (kid más HMAC) acotado a una zona, para el newAccount de un cliente ACME.
ListAcmeAccounts / ListAcmeCertificatesCuentas ACME registradas y certificados emitidos.

DHCP

MétodoPara qué sirve
AddDhcpPool / RemoveDhcpPool / ListDhcpPoolsRangos de direcciones para asignar dentro de un alcance.
ListDhcpLeases / DeleteDhcpLeaseConcesiones de dirección, borradas por dirección MAC.
SetDhcpCertOption / RemoveDhcpCertOption / ListDhcpCertOptionsUn certificado entregado a los clientes por DHCP para un alcance.

Diagnóstico y ajuste

MétodoPara qué sirve
GetCacheStats / FlushDnsCacheEstadísticas de caché, y limpieza de la caché de respuestas.
GetQueryLatencyStatsLatencia de las consultas externas.
SetTtlDriftConfig / GetTtlDriftConfigConfiguración de deriva de TTL.
SetTrackedTlds / ListTrackedTldsLa lista de TLD vigilados detrás de las métricas por TLD, guardada y efectiva.
SetDns64Config / GetDns64ConfigConfiguració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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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étodoDescripció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

ObjetivoDescripción
make devLevanta todo el entorno de desarrollo (backend + servidor de Vite).
make dev-stopDetiene y elimina el contenedor del backend de desarrollo.
make dev-logsSigue journalctl dentro del contenedor de desarrollo en marcha.
make dev-cleanDetiene el contenedor y desmonta el volumen btrfs de desarrollo.

Objetivos de pruebas

ObjetivoDescripción
make testCorre el análisis estático y las pruebas unitarias de Go y de JS.
make test-integrationCorre las pruebas de integración de Go en un contenedor de Podman con privilegios.
make test-ui-integrationCorre las pruebas de integración de la interfaz con Bun contra un contenedor del backend.
make test-fullCorre todas las suites de pruebas en orden.
make auto-testVigila los cambios de archivos y vuelve a correr las pruebas solo.

Objetivos de construcción

ObjetivoDescripción
make production-imageConstruye la imagen de contenedor de producción.
make test-imageConstruye la imagen de contenedor de pruebas.
make pull-imagesDescarga 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-progsmkfs.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.