farmd MVP scaffold: HTTP server, healthz, dashboard placeholder

Go printer-farm manager (Wave 1, Redmine #855). Cloudron-deployable,
OIDC via platform provider planned; Moonraker/OctoPrint/Bambu adapters
+ Dolibarr connector are the next milestones. Dockerfile: multi-stage,
non-root, no Node anywhere in the chain.
This commit is contained in:
2026-09-07 08:07:25 -05:00
commit 18f54afcac
6 changed files with 108 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
farmd
*.db
+19
View File
@@ -0,0 +1,19 @@
# STLP Shop Manager (farmd) - Go printer-farm manager.
# Multi-stage: build in golang, run minimal alpine. No Node anywhere.
FROM golang:1.23-alpine AS build
WORKDIR /src
COPY go.mod ./
COPY cmd/ ./cmd/
COPY internal/ ./internal/
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /out/farmd ./cmd/farmd
FROM alpine:3.20
RUN apk add --no-cache ca-certificates && adduser -D -u 1000 app
COPY --from=build /out/farmd /usr/local/bin/farmd
COPY web/templates/ /app/web/templates/
USER 1000:1000
ENV FARMD_ADDR=:3000 FARMD_DB_PATH=/app/data/farmd.db
VOLUME /app/data
EXPOSE 3000
HEALTHCHECK CMD wget -qO- http://127.0.0.1:3000/healthz || exit 1
ENTRYPOINT ["/usr/local/bin/farmd"]
+27
View File
@@ -0,0 +1,27 @@
# STLP Shop Manager
Go printer-farm manager for Starting Line Productions — Etsy batch printing
with Dolibarr ERP/MRP integration. Cloudron-deployable, OIDC via the platform
provider.
Design + proposal: Redmine [#855](https://projects.knownelement.com/issues/855)
(program: [#836](https://projects.knownelement.com/issues/836), RDStack).
## Status
MVP scaffold: HTTP server + /healthz + dashboard placeholder. Next: printer
adapters (Moonraker/Klipper, OctoPrint, Bambu), job queue + state machine,
Dolibarr connector, OIDC login (Cloudron platform provider).
## Build & run
go build ./cmd/farmd
FARMD_ADDR=:3000 FARMD_DB_PATH=/tmp/farmd.db ./farmd
Docker: `docker build -t farmd .` (serves :3000, data at /app/data).
## Layout
cmd/farmd/ entrypoint
internal/server/ HTTP surface (healthz, dashboard)
web/templates/ embedded dashboard templates
+3
View File
@@ -0,0 +1,3 @@
module git.knownelement.com/StartingLineProductions.com/STLPShopManager
go 1.23
+46
View File
@@ -0,0 +1,46 @@
// Package server wires the HTTP surface: health, dashboard, and (coming)
// the printer/job APIs. See Redmine #855 for the component design.
package server
import (
"fmt"
"html/template"
"net/http"
)
type Config struct {
Addr string
DBPath string
}
type Server struct {
cfg Config
mux *http.ServeMux
}
func New(cfg Config) *Server {
s := &Server{cfg: cfg, mux: http.NewServeMux()}
s.mux.HandleFunc("/healthz", s.health)
s.mux.HandleFunc("/", s.index)
return s
}
func (s *Server) Run() error {
return http.ListenAndServe(s.cfg.Addr, s.mux)
}
func (s *Server) health(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, "ok")
}
// index is the farm dashboard placeholder. The real board (printer cards,
// job queue, batch view) lands with the printer adapters.
func (s *Server) index(w http.ResponseWriter, _ *http.Request) {
t, err := template.ParseFiles("web/templates/index.html")
if err != nil {
http.Error(w, "template: "+err.Error(), http.StatusInternalServerError)
return
}
_ = t.Execute(w, map[string]string{"Toolset": "farmd 0.1.0-dev"})
}
+11
View File
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>STLP Shop Manager</title>
<style>body{font-family:system-ui,sans-serif;max-width:60rem;margin:2rem auto;padding:0 1rem}h1{color:#0a7}code{background:#eee;padding:.1rem .3rem}</style>
</head>
<body>
<h1>STLP Shop Manager</h1>
<p>Printer farm manager — build {{.Toolset}}. Dashboard under construction (Redmine #855).</p>
<p>Planned: printer cards (Moonraker/OctoPrint/Bambu), job queue, Etsy batch view, Dolibarr sync.</p>
</body>
</html>