Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

102 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DurpDeploy

A single-binary deployment tool for running bash scripts against environments. Define projects, write deployment steps, manage environment-scoped variables, create immutable releases, and deploy them with live log streaming in the browser.

*** This Application is a test of "Vibe Coding" and what can and cannot be done with AI ***

Main Screen

Features

  • Projects - Organize deployments into projects
  • Environments - Define deployment targets (dev, staging, prod) with tags
  • Steps - Ordered bash scripts that run sequentially during deployment
  • Variables - Key/value pairs scoped to environments, resolved at deploy time
  • Releases - Immutable snapshots of steps + variables with version numbers
  • Deployments - Execute releases against environments with live SSE log streaming
  • Approvals - Manual gate for production deployments requiring admin sign-off
  • Notifications - Event-driven Slack, Email, Gotify, and Discord alerts for deployment status
  • Cancel - Stop running deployments mid-execution

Quick Start

Prerequisites

  • Go 1.25+
  • Node.js (for Tailwind CSS build)
  • templ CLI
  • sqlc (only if modifying queries)

Build

npm install
make build

This produces a single durpdeploy binary.

Run

./durpdeploy

Server starts on http://localhost:8080. A durpdeploy.db SQLite file is created automatically on first run.

Usage

  1. Create a project - Navigate to Projects → New Project
  2. Add steps - On the project detail page, add bash script steps in order
  3. Create environments - Navigate to Environments → New Environment (e.g., "Production" with tag prod)
  4. Add variables - On the project detail page, click Variables. Add key/value pairs scoped to environments
  5. Create a release - On the project detail page, click Releases. Enter a version (e.g., 1.0.0)
  6. Deploy - On the release, select an environment and click Deploy. Watch logs stream in real time.

API

DurpDeploy exposes a JSON REST API at /api/v1/*. All requests must authenticate with a bearer token:

curl -H "Authorization: Bearer ddp_pat_<token>" http://localhost:8080/api/v1/projects

API tokens are created per-user from the /settings/tokens page or via the CLI:

durpdeploy tokens create --user admin@example.com --name ci

The full API reference is available at /api/swagger/ in a running server (no auth required).

Architecture

cmd/server/main.go        Entry point
internal/
  handler/                HTTP handlers (chi routes)
  repository/             Thin wrapper around sqlc-generated queries
  runner/                 Deployment execution engine + SSE log broker
  server/                 Router setup
  migrate/                Goose migration runner
migrations/               SQL schema migrations
queries/                  sqlc query definitions
views/                    Templ templates (pages, components, layouts)
static/                   Embedded static assets (JS, CSS)

Stack: Go + chi + SQLite (modernc.org/sqlite) + sqlc + goose + Templ + HTMX + Alpine.js + Tailwind CSS + DaisyUI

Development

# Generate templ files
make templ-generate

# Build Tailwind CSS
make tailwind-build

# Full build
make build

# Run with hot-reload (requires air or similar)
make dev

Production Deploy

For a small team deployment, DurpDeploy runs as a single Go process behind Caddy, which terminates HTTPS and reverse-proxies to localhost:8080. The binary ships with argon2id password hashing, DB-backed session auth, CSRF protection on every state-changing request, and an audit log. See docs/deploy.md for the full runbook — provisioning a fresh Debian 12 VM end to end takes about 20 minutes.

The first admin user is created with a one-shot CLI command (no server running required). The password is hashed with argon2id and stored in the users table; nothing in the DB is plaintext:

durpdeploy admin create --email admin@example.com --password '<strong-password>'

The database path is configurable via the DURPDEPLOY_DB env var; it defaults to durpdeploy.db in the current directory for local dev. Production sets it to /var/lib/durpdeploy/durpdeploy.db via the systemd unit.

Roles

Three roles, set at user-creation time and stored in users.role:

Role Reads Writes Sees audit log
admin Everything Everything Yes (/admin/audit)
deployer Everything Everything — same writes as admin No
viewer Everything Nothing — every POST/PUT/PATCH/DELETE returns 403 No

Per-project authorization is enforced — every project has a project_members row for each user who can read or write to it. Global admins bypass the check; non-admins must be a member. A non-member hitting a project-scoped route gets 404 (to hide existence) or 403 (depending on the route). The practical "least privilege" is to make non-admins viewer if they don't need to trigger deploys. Full details in docs/roles.md.

Security

The threat model — what DurpDeploy defends against, what it doesn't, and the five-minute hands-on attack drill — is documented in docs/attack-drill.md. The summary:

  • Defends against: unauthenticated deploys, CSRF on a teammate's browser, password DB leak (argon2id, per-user salt, ~100ms per guess), cross-project write access (per-project project_members — P1-1), secret-at-rest exposure (AES-256-GCM for variables and release_variables.value — P1-3), rogue step scripts (dedicated user + cgroup sandbox + minimal env — P1-4), naive log redaction (regex-based scrubber for literal secrets, common credential patterns, and split writes — P1-5), unrecoverable data loss (Litestream continuous WAL replication + monthly restore drill — P1-6), and unauthorized approval of pending_approval deployments (admin-only gate on /deployments/{id}/approve — P2-1; the stored required_approver_role is descriptive only, the real gate is the handler check).
  • Partially defends against: backup monitoring (P2-4 — the binary polls a user-supplied check command and fires BackupUnhealthy on failure, but does not enforce the originally planned 36h age threshold). Audit retention (P2-5 — audit prune --days N ships and preserves rows tied to live deployments/releases, but the default 180-day window and the daily systemd timer are operator-deployed, not auto-installed).

What It Does Not Do

  • No remote deployment targets or SSH
  • No parallel step execution
  • No CI/build features
  • No Kubernetes or cloud integrations
  • No PowerShell support (bash only)

License

MIT

About

No description, website, or topics provided.

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages