You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+5-1Lines changed: 5 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# StackHost
2
2
3
-
StackHost is an early-stage, self-hosted control panel for Docker and Docker Swarm. It provides first-admin onboarding, cookie sessions, SQLite persistence, projects, and an infrastructure-aware dashboard.
3
+
StackHost is an early-stage, self-hosted control panel for Docker and Docker Swarm. It provides first-admin onboarding, cookie sessions, SQLite persistence, projects, applications, Docker inventory, and an infrastructure-aware dashboard in Portuguese (Brasil).
4
4
5
5
## Local development
6
6
@@ -16,6 +16,10 @@ Open http://localhost:8080. A clean database redirects users to `/setup` in the
16
16
17
17
For frontend hot reload during development, run `cd web && npm run dev` in a second terminal. The Vite server proxies the UI only; the Go server remains responsible for the API.
18
18
19
+
When Docker is connected without Swarm, open **Infraestrutura** and use **Preparar ambiente**. The operation uses the Docker Engine SDK, requires an administrator session, records an audit event, and never removes existing containers, images, or volumes. Docker socket access is intentionally explicit because it grants elevated access to the host.
20
+
21
+
The initial read-only inventory APIs are `/api/v1/infrastructure/containers`, `/images`, `/volumes`, and `/networks`; each accepts `limit` and returns bounded DTOs.
ifrows, err:=a.db.Query("SELECT id,name,(SELECT count(*) FROM applications a WHERE a.project_id=projects.id),updated_at FROM projects ORDER BY updated_at DESC LIMIT 4"); err==nil {
descriptions:=map[string]string{"login": "Entrou no painel", "logout": "Saiu do painel", "onboarding": "Criou o administrador inicial", "project.created": "Criou um projeto", "project.updated": "Atualizou um projeto", "application.created": "Adicionou uma aplicação", "application.updated": "Atualizou uma aplicação", "swarm.initialized": "Preparou o ambiente Docker"}
rows, err:=a.db.Query("SELECT id,action,coalesce(resource_type,''),coalesce(resource_id,''),created_at FROM audit_logs ORDER BY id DESC LIMIT 50")
368
+
rows, err:=a.db.Query("SELECT audit_logs.id,audit_logs.action,coalesce(audit_logs.resource_type,''),coalesce(audit_logs.resource_id,''),audit_logs.created_at,coalesce(users.name,'Administrador') FROM audit_logs LEFT JOIN users ON users.id=audit_logs.user_id ORDER BY audit_logs.id DESC LIMIT 50")
350
369
iferr!=nil {
351
370
jsonError(w, 500, "internal_error", "Não foi possível carregar a atividade.")
352
371
return
@@ -355,23 +374,24 @@ func (a *app) activity(w http.ResponseWriter, r *http.Request) {
rows, _:=a.db.Query("SELECT id,name,slug,coalesce(description,''),status,created_at,updated_at FROM projects ORDER BY id DESC")
386
+
rows, _:=a.db.Query("SELECT id,name,slug,coalesce(description,''),status,created_at,updated_at,(SELECT count(*) FROM applications a WHERE a.project_id=projects.id) FROM projects ORDER BY id DESC")
jsonError(w, http.StatusUnprocessableEntity, "advertise_address_required", "O Docker precisa de um endereço de anúncio. Abra as opções avançadas e informe o endereço desta máquina.")
743
+
return
744
+
}
745
+
jsonError(w, 422, "swarm_init_failed", "Não foi possível preparar o ambiente Docker. Verifique a rede do servidor e tente novamente.")
0 commit comments