A Vukem app compiles to a single executable. With embed, views and public assets ship inside it, so a deployment is one file plus its environment.
Build#
CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o bin/app ./cmd/appSQLite uses the pure-Go modernc.org/sqlite driver, so no cgo toolchain is needed and cross-compiling is a matter of GOOS/GOARCH.
vukem build does this for you: it runs npx vite build when a vite.config.* exists, then go build -trimpath -ldflags="-s -w" -o bin/app ./cmd/app (-o changes the output). The starter embeds resources/views and resources/public with //go:embed, so the binary is self-contained.
Embed public assets#
//go:embed public
var publicFS embed.FS
func staticMiddleware() (middleware.Middleware, error) {
sub, err := fs.Sub(publicFS, "public")
if err != nil {
return nil, err
}
return middleware.StaticFS(sub, middleware.StaticConfig{}), nil
}Configure production#
APP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com
HOST=0.0.0.0
PORT=3000
LOG_FORMAT=json
SHUTDOWN_TIMEOUT=20sProvide APP_KEY through the environment or a secret file (APP_KEY=@file:/run/secrets/app_key). The app refuses to boot with APP_DEBUG=true in production.
Run#
APP_ENV=production ./bin/appOn SIGINT or SIGTERM the HTTP server stops accepting connections, drains in-flight requests, then runs shutdown hooks and providers in reverse order within SHUTDOWN_TIMEOUT. Pair it with your process manager's stop timeout.
Behind a reverse proxy#
Terminate TLS at the proxy (Caddy, nginx, a load balancer) and tell Vukem which proxies to trust:
_, proxy, _ := net.ParseCIDR("10.0.0.0/8")
services := &web.Services{TrustedProxies: []*net.IPNet{proxy}}
r.UseServer(middleware.SecureHeaders(middleware.SecureHeadersConfig{
TrustForwardedProto: true, // send HSTS when the proxy says the request was HTTPS
}))Checklist#
APP_ENV=production,APP_DEBUG=false, a uniqueAPP_KEY.APP_URLset to thehttpsorigin.- Trusted proxies configured; HSTS enabled behind TLS.
- Logs shipped as JSON to durable storage, with alerts on security events.
govulncheck ./...in CI.