Help us shape the future of Go! Take the 2026 Go Developer Survey

dinchy

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2026 License: Apache-2.0

README

Dinchy

A lightweight, self-hosted deployment manager for homelabs and small teams. A better alternative to Dokploy and Coolify — polished UI, low memory footprint, first-class SSO, and a build system that doesn't crash your server.

Why Dinchy?

Dokploy Coolify Dinchy
Idle memory 350-600MB 500-700MB < 200MB target
API design tRPC REST REST
SSO out of the box No Partial Yes
Build safety None None Memory guardian
Distribution Docker Docker Single binary
Tech stack Next.js + PostgreSQL + Redis Laravel + PostgreSQL Go + PostgreSQL

Architecture

                    User traffic (80/443)
                          ↕
┌──────────────────┐  localhost:2019  ┌────────────────────┐
│  Dinchy binary   │ ── Admin API ──→ │  Caddy (sidecar)   │
│                  │                  │  - Reverse proxy    │
│  - REST API      │                  │  - Auto HTTPS       │
│  - React UI      │                  └────────────────────┘
│  - WebSocket     │
│  - Terminal (PTY)│                  ┌────────────────────┐
│  - PostgreSQL    │ ── Docker/Podman ─→│  User containers   │
└──────────────────┘                  └────────────────────┘
        ↑
  systemd / OpenRC

Single-node, single binary. Caddy runs alongside as a sidecar and handles all routing and HTTPS.

Tech Stack

  • Backend: Go — single binary, no runtime dependencies
  • Database: PostgreSQL — single supported datastore
  • Frontend: React + Vite + Tanstack Router + Shadcn/ui — statically served from the binary via embed.FS
  • Reverse proxy: Caddy — programmatically controlled via JSON Admin API, automatic HTTPS
  • Process supervision: systemd (Debian, Ubuntu, Fedora, Arch, Proxmox) + OpenRC (Alpine, Gentoo)

Features (v1)

  • Three deployment modes:
    • Docker Compose — paste a compose file, Dinchy manages the lifecycle
    • Container image — specify an image + ports + env vars, done
    • Git + Dockerfile — point at a repo, Dinchy builds and deploys
  • Private registry support — configure credentials for Docker Hub, ghcr.io, self-hosted registries
  • Build Resource Guardian — pre-flight memory checks, build queue, memory watchdog, graceful abort instead of OOM crashes
  • Authentication: email/password, OAuth/OIDC (Google, GitHub, Authentik, Authelia, Keycloak), 2FA (TOTP), forgot password, first-user setup
  • Authorization: Casbin RBAC — Admin / Deployer / Viewer roles
  • Automatic HTTPS — via Caddy + Let's Encrypt, zero config
  • Web terminal — browser-based shell access without SSH keys
  • Log viewer — real-time streaming, historical search (SQLite FTS5), syntax-highlighted by log level
  • Secrets management — AES-256-GCM encrypted env vars, masked in UI
  • Monitoring: container CPU/memory sparklines, HTTP health checks, uptime graphs
  • Alerts: webhook-based (works with ntfy, Slack, Discord, email, anything)
  • Deploy history + rollback — one-click rollback to any previous state
  • Auto-updates — updater binary with checksum verification and auto-rollback on failure

Roadmap

See docs/plan.md for the full phased implementation plan.

Detailed Phase 1 implementation docs live in docs/implementation/phase-1/.

v2+:

  • Multi-node support (gRPC master/agent architecture)
  • Plugin ecosystem (container-based plugins)
  • App template store
  • Podman support
  • External secret managers (Vault, SOPS)
  • Scheduled jobs

Installation

Coming in Phase 8.

curl -fsSL https://dinchy.com/install.sh | bash

Development

This project uses mise to manage all tooling. First-time setup:

mise install               # install pinned Go, Bun, Node, dlv, and dev tools
cp .env.example .env       # your local config (gitignored) — edit as needed
mise run infra:up          # start Postgres + Redis (podman-compose)
mise run db:migrate        # apply database migrations
mise run dev               # run the backend — colored, human-readable logs

.env.example is the only committed template. Copy it to .env (gitignored) for your working config — including DINCHY_LOG_FORMAT=text, which produces colored, human-readable logs in a terminal, and the Postgres DSN. An optional .env.local (also gitignored) can hold personal overrides; mise loads both, with .env.local winning over .env.

Local Postgres + Redis run from compose.yaml via podman-compose (a mise-managed tool that drives podman directly — no Docker daemon or socket). The host ports are configurable via env: compose.yaml interpolates DINCHY_POSTGRES_PORT / DINCHY_REDIS_PORT from .env (default 5433 / 6380, to avoid clashing with anything already on 5432 / 6379). Keep the DSN / DINCHY_REDIS_ADDR ports in sync with those keys.

WSL2 note: if mise run infra:up fails with netavark: nftables error, uncomment NETAVARK_FW=none in your .env (nftables is unusable on some WSL2 kernels; rootless port forwarding still works without it). On native Linux, leave it unset so podman uses its default nftables firewall.

Everyday tasks:

mise run dev          # run the Go backend in development mode
mise run test         # run the test suite
mise run lint         # run the linter
mise run build        # build the production binary
mise run generate     # regenerate generated Go code and sqlc queries
mise run db:migrate   # run database migrations against DINCHY_POSTGRES_DSN
mise run infra:up     # start local Postgres + Redis (podman-compose)
mise run infra:down   # stop local Postgres + Redis
mise run infra:logs   # follow pg/redis logs

Optional one-time podman hardening: sudo loginctl enable-linger $USER gives your user a persistent systemd session so podman uses the systemd cgroup manager and the rootless cgroupfs-fallback warnings disappear. Not required — the infra works without it.

Debugging in Zed

.zed/debug.json defines a dinchy (dev) configuration that launches cmd/dinchy under Delve (dlv, installed by mise install). Set a breakpoint and start that configuration; its environment is loaded entirely from .env + .env.local via envFile, so nothing sensitive is committed and edits to those files take effect on the next launch. .zed/tasks.json also exposes the mise tasks (dev, infra up/down, migrate, test, …) in Zed's task runner (task: spawn).

Open this repo as the Zed project root, not a parent folder. The debug config and tasks resolve paths via $ZED_WORKTREE_ROOT, which Zed sets to the folder you opened. If you open an ancestor (e.g. a multi-project workspace), $ZED_WORKTREE_ROOT points there and the debugger fails with package cmd/dinchy is not in std. Open the directory that contains this README.md.

When the frontend exists:

mise run web:install  # install frontend dependencies (via Bun)
mise run web:dev      # run the frontend dev server (Bun runtime)
mise run web:build    # build production frontend assets

Bun is the primary JS runtime for this project. Node is available via mise for compatibility, but all frontend tasks run through Bun.

The database is PostgreSQL only. DINCHY_POSTGRES_DSN is supplied by .env.local for local dev; set it explicitly in other environments.

License

MIT

Directories

Path Synopsis
cmd
codegen command
Command codegen generates i18n, event, and permission source from their hand-written catalogs.
Command codegen generates i18n, event, and permission source from their hand-written catalogs.
coderules command
Package main implements the coderules binary that enforces Dinchy codebase invariants via static analysis.
Package main implements the coderules binary that enforces Dinchy codebase invariants via static analysis.
dinchy command
Package main is the entry point for the Dinchy server binary.
Package main is the entry point for the Dinchy server binary.
validate command
Command validate checks the i18n, event, and permission catalogs against their schemas without regenerating code.
Command validate checks the i18n, event, and permission catalogs against their schemas without regenerating code.
internal
app
Package app wires the application dependencies together and owns the server lifecycle.
Package app wires the application dependencies together and owns the server lifecycle.
config
Package config loads application startup configuration from environment variables.
Package config loads application startup configuration from environment variables.
features
Package features provides the shared service base that every feature service embeds.
Package features provides the shared service base that every feature service embeds.
features/audit
Package audit records and serves audit log entries for security-relevant events.
Package audit records and serves audit log entries for security-relevant events.
features/auth
Package auth handles authentication, sessions, account setup, and related feature flows.
Package auth handles authentication, sessions, account setup, and related feature flows.
features/health
Package health serves liveness and readiness probes for the process.
Package health serves liveness and readiness probes for the process.
features/session
Package session owns authenticated request principals, session cookies, and session request middleware.
Package session owns authenticated request principals, session cookies, and session request middleware.
foundation/clock
Package clock provides a mockable time source for testability.
Package clock provides a mockable time source for testability.
foundation/errors
Package errors provides structured, localizable application errors.
Package errors provides structured, localizable application errors.
foundation/i18n
Package i18n resolves message codes to localized text for supported locales.
Package i18n resolves message codes to localized text for supported locales.
foundation/id
Package id provides UUIDv7 generation.
Package id provides UUIDv7 generation.
foundation/permission
Package permission defines built-in access permissions and roles.
Package permission defines built-in access permissions and roles.
foundation/requestmeta
Package requestmeta carries request-scoped observability values — client IP, user agent, and request, trace, and span IDs — across layers via the context.
Package requestmeta carries request-scoped observability values — client IP, user agent, and request, trace, and span IDs — across layers via the context.
foundation/security
Package security hashes passwords and generates tokens for authentication.
Package security hashes passwords and generates tokens for authentication.
foundation/transform
Package transform provides small pure string normalization helpers.
Package transform provides small pure string normalization helpers.
manifest
Package manifest parses and validates code-generation manifests.
Package manifest parses and validates code-generation manifests.
platform/cache
Package cache provides Redis connection setup, shared key namespacing, and a typed, namespaced cache entry so callers address cached values by identifier alone and never build key strings by hand.
Package cache provides Redis connection setup, shared key namespacing, and a typed, namespaced cache entry so callers address cached values by identifier alone and never build key strings by hand.
platform/email
Package email renders resolved Content into a shared branded layout and delivers it durably through a background job.
Package email renders resolved Content into a shared branded layout and delivers it durably through a background job.
platform/events
Package events provides a Redis-stream-backed event bus that publishes domain events and dispatches them to registered subscribers via consumer groups.
Package events provides a Redis-stream-backed event bus that publishes domain events and dispatches them to registered subscribers via consumer groups.
platform/frontend
Package frontend serves the compiled web UI assets from the top-level web workspace.
Package frontend serves the compiled web UI assets from the top-level web workspace.
platform/jobs
Package jobs provides a durable, Postgres-backed background job queue (River) for on-demand work that must survive restarts and is retried until it succeeds.
Package jobs provides a durable, Postgres-backed background job queue (River) for on-demand work that must survive restarts and is retried until it succeeds.
platform/logging
Package logging configures structured application logging and telemetry.
Package logging configures structured application logging and telemetry.
platform/store
Package store is the postgres-backed persistence implementation.
Package store is the postgres-backed persistence implementation.
platform/store/sqltype
Package sqltype converts Go values to and from pgx nullable column types.
Package sqltype converts Go values to and from pgx nullable column types.
transport
Package transport configures the Chi HTTP router, mounts middleware, and wires API routes.
Package transport configures the Chi HTTP router, mounts middleware, and wires API routes.
transport/middleware
Package middleware provides HTTP middleware for the transport layer.
Package middleware provides HTTP middleware for the transport layer.
transport/render
Package render localizes application errors into transport-layer HTTP responses for Huma.
Package render localizes application errors into transport-layer HTTP responses for Huma.
transport/support
Package support provides shared transport helpers for the HTTP server layer.
Package support provides shared transport helpers for the HTTP server layer.
workers
Package workers constructs the background job scheduler and registers the recurring jobs the application owns.
Package workers constructs the background job scheduler and registers the recurring jobs the application owns.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL