Continuous integration and continuous deployment pipelines are the backbone of modern software development. Every code change needs to be built, tested, scanned, and deployed reliably. The traditional approach ties your pipeline logic to a specific platform — Jenkins, GitHub Actions, GitLab CI — meaning your build scripts are locked into that provider’s syntax, runtime, and ecosystem.
Dagger takes a fundamentally different approach. It is an open-source engine that lets you define your CI/CD pipelines as portable programs that run anywhere: on your local laptop, inside a self-hosted server, or as a step inside any existing CI platform. This guide walks you through self-hosting Dagger, writing your first pipelines, and understanding when this portable paradigm makes sense for your infrastructure.
Why Self-Host Your CI/CD Pipeline Engine
Running your own pipeline infrastructure offers advantages that go beyond simple cost savings:
No build minute limits or queue times. Commercial CI platforms throttle concurrent jobs, cap monthly build minutes, and charge premium rates for parallel runners. A self-hosted Dagger engine on a dedicated server runs as many pipelines as your hardware can handle, with no artificial constraints.
Full pipeline portability. Dagger pipelines are defined as executable programs, not YAML declarations bound to a specific platform. The same pipeline runs identically on a developer’s laptop, a staging server, and your production CI infrastructure. You can test pipeline changes locally before pushing them — something that is nearly impossible with traditional platform-specific CI configs.
Data sovereignty and compliance. Build artifacts, test results, and deployment logs never leave your infrastructure. For organizations handling regulated data, this eliminates the risk of third-party CI platforms storing sensitive build outputs or leaking metadata about your codebase.
Reduced CI/CD vendor lock-in. If you define your pipelines in Dagger and your CI platform goes down, changes pricing, or introduces breaking changes, you are not stranded. Dagger runs independently — you can point it at a new CI provider, a bare-metal server, or a Kubernetes cluster with zero pipeline rewrites.
Cost efficiency at scale. Managed CI services charge per build minute, with rates climbing as you add concurrency. A self-hosted server running Dagger costs a flat monthly rate regardless of how many pipelines execute. For teams running hundreds of builds daily, this difference is significant.
What Makes Dagger Different
Most CI/CD tools define pipelines as static configuration files. Jenkins uses Groovy-based Jenkinsfiles. GitHub Actions uses YAML workflows. GitLab CI uses .gitlab-ci.yml. Each is interpreted by a specific platform with its own runner architecture, environment assumptions, and plugin ecosystem.
Dagger treats pipelines as programs. You write pipeline logic in familiar languages (Go, Python, TypeScript, or CUE) using the Dagger SDK. The engine executes your code inside containers, giving you deterministic, reproducible builds by default. The key architectural differences:
| Feature | Dagger | Jenkins | GitHub Actions | Tekton |
|---|---|---|---|---|
| Pipeline format | Programs (Go, Python, TS, CUE) | Groovy (Jenkinsfile) | YAML workflows | YAML CRDs |
| Execution | Container-native | Agent-based | Cloud runners | Kubernetes pods |
| Local testing | Native (dagger run) | Limited | Via act (imperfect) | Via tkn (complex) |
| Portability | Run anywhere | Jenkins-specific | GitHub-specific | Kubernetes-only |
| Caching | Automatic content-addressed | Manual config | Limited | Manual volumes |
| Parallelism | Built-in (concurrent modules) | Parallel stages | Matrix strategy | Parallel tasks |
| License | Apache 2.0 | MIT / BSL | Proprietary | Apache 2.0 |
Dagger’s content-addressed caching system is particularly powerful. Every file, directory, and container image is identified by a cryptographic hash. If nothing has changed since the last run, Dagger reuses cached results instantly — no manual cache key configuration required.
Installing Dagger on Your Server
Dagger is distributed as a single binary. Installation is straightforward on any Linux server:
| |
Dagger requires a container runtime. Docker is the default, but Podman and containerd are also supported. For a self-hosted production server, Docker is recommended due to its stability and broad compatibility.
Installing Docker
| |
Writing Your First Dagger Pipeline
Here is a complete example of a Dagger pipeline written in CUE that builds, tests, and deploys a Go application:
| |
Run this pipeline locally to verify it works before deploying:
| |
The dagger run command executes the pipeline on your local machine, showing real-time logs. If it passes locally, it will pass identically on your CI server — no “works on my machine” surprises.
Self-Hosting Dagger with Docker Compose
For a production self-hosted setup, you can run Dagger’s engine alongside a container registry for storing build artifacts. Here is a Docker Compose configuration:
| |
Deploy this stack on any server with Docker:
| |
The local registry at localhost:5000 stores all container images built by your pipelines. This gives you a complete, self-contained CI/CD infrastructure with no external dependencies.
Real-World Pipeline Examples
Multi-Stage Build with Linting and Testing
| |
Python Application with Database Integration Tests
| |
Cross-Platform Container Build
Building multi-architecture images is straightforward with Dagger’s built-in platform support:
| |
Dagger vs Traditional CI/CD: When to Use Each
Dagger does not replace your CI platform — it replaces the pipeline logic inside it. The right approach depends on your team’s needs:
Choose Dagger when:
- Your team uses multiple CI platforms (some repos on GitHub Actions, others on GitLab CI) and wants a single pipeline definition
- Developers need to debug pipeline failures locally instead of pushing commits to trigger CI
- You want content-addressed caching without manual cache key configuration
- You are building a self-hosted CI infrastructure from scratch and want a portable foundation
- Your pipelines involve complex logic that is awkward to express in YAML
Stick with traditional CI/CD YAML when:
- Your team uses a single CI platform exclusively
- Your pipelines are simple: build, test, deploy in linear steps
- Your team is not comfortable writing pipeline code in Go, Python, or TypeScript
- You need deep integration with platform-specific features (GitHub Environment protections, GitLab review apps)
For most self-hosted infrastructure teams, the best approach is hybrid: define your core pipeline logic in Dagger for portability, then invoke it from a lightweight CI runner (like Woodpecker CI or a cron job on your server). This gives you local debuggability and cross-platform portability while still using your existing CI infrastructure for triggering.
For related reading, see our guide to self-hosted CI/CD platforms for runner options, and our comparison of container build tools for alternative approaches to container-based pipelines. If you are deploying to Kubernetes, check our Kubernetes CNI guide for networking setup.
FAQ
Is Dagger free for self-hosted use?
Yes. Dagger is open source under the Apache 2.0 license. The engine runs entirely on your own infrastructure with no licensing fees. Dagger Cloud offers optional hosted features (remote caching, pipeline analytics, team management), but the core engine and SDK are fully self-contained and free.
Can Dagger replace Jenkins entirely?
Dagger replaces the pipeline definition and execution layer, not the scheduling and orchestration layer. Jenkins handles job scheduling, queue management, user authentication, and plugin integrations. Dagger handles what happens inside each pipeline step. You can run Dagger pipelines from Jenkins, from cron, or from any script — but you would still need a scheduler to trigger them.
What programming languages does Dagger support?
Dagger SDKs are available for Go, Python, TypeScript, and CUE (its own configuration language). The CUE SDK is the most mature and is recommended for most pipeline definitions. The Go SDK gives you full programmatic control for complex logic. Python and TypeScript SDKs are ideal for teams already working in those ecosystems.
How does Dagger handle secrets?
Dagger provides a #Secret type that stores sensitive values encrypted in memory. Secrets are never written to disk or included in the content-addressed cache. You can pass secrets into pipeline steps as environment variables or mounted files. For self-hosted deployments, integrate with Vault, SOPS, or any secrets manager by loading values into Dagger’s secret store before pipeline execution.
Does Dagger require Docker?
Dagger defaults to Docker as its container runtime, but it also supports Podman, containerd, and nerdctl. For environments where Docker is not available (such as restricted enterprise servers), you can configure Dagger to use an alternative runtime via the _EXPERIMENTAL_DAGGER_RUNNER_HOST environment variable.
Can I run Dagger pipelines on Kubernetes?
Yes. Dagger can run on any platform that supports containers, including Kubernetes clusters. You can deploy the Dagger engine as a StatefulSet and execute pipelines from worker pods. For production Kubernetes deployments, consider using the Dagger Helm chart, which handles RBAC, persistent volumes, and engine scaling automatically.