← All articles
a close up of a computer and wires in a dark room

Gitness: Self-Hosted Git and CI/CD From the Makers of Drone

Development 2026-02-15 · 6 min read gitness harness ci-cd git-hosting pipelines docker devops
By Selfhosted Guides Editorial TeamSelf-hosting practitioners covering open source software, home lab infrastructure, and data sovereignty.

Running separate services for Git hosting and CI/CD works, but it means maintaining two systems, two sets of credentials, and an integration layer between them. Gitea plus Woodpecker is a proven combo, but what if a single service handled both?

Photo by Vitaly Sacred on Unsplash

Gitness (formerly Harness Open Source) is a lightweight, self-hosted platform that combines Git repository hosting with a built-in CI/CD pipeline engine. It comes from the team behind Drone CI, and it shows -- the pipeline syntax is clean, the system is container-native, and the resource footprint stays small.

Gitness CI/CD platform logo

Why Gitness Exists

Gitness fills a gap in the self-hosted development tool space. GitLab gives you everything but demands significant resources. Gitea and Forgejo are excellent Git forges but require a separate CI/CD system. Jenkins is powerful but complex. Gitness takes a middle path: a single binary that handles both code hosting and pipeline execution without consuming half your server's RAM.

It grew out of Harness's acquisition of Drone CI. Rather than continuing Drone as a standalone CI tool, Harness built Gitness as a unified platform that inherits Drone's pipeline philosophy while adding native Git hosting.

Gitness vs. Other Self-Hosted CI/CD and Git Platforms

Feature Gitness Gitea + Woodpecker GitLab CE Forgejo + Drone
Git hosting Built-in Gitea Built-in Forgejo
CI/CD Built-in Separate service Built-in Separate service
Setup complexity Single container Two containers + OAuth Heavy (requires 4 GB+ RAM) Two containers + OAuth
RAM usage (idle) ~150 MB ~120 MB combined ~2.5 GB ~120 MB combined
Pipeline syntax YAML (Drone-derived) Woodpecker YAML GitLab CI YAML Drone YAML
GitHub Actions compat No No (Gitea Actions: Yes) No No
Container registry No Gitea packages Built-in No
Code review Pull requests Pull requests Merge requests Pull requests
Issue tracking No Yes Yes Yes
Plugin ecosystem Drone plugins Woodpecker plugins Large Drone plugins
License Apache 2.0 Apache 2.0 / GPL MIT (CE) GPL

Choose Gitness if you want the simplest possible path to Git hosting with CI/CD and don't need issue tracking. Choose Gitea + Woodpecker if you want a full-featured forge with issue tracking and proven CI/CD. Choose GitLab CE if you need everything in one box and have resources to spare.

Installation

Gitness ships as a single Docker image. No database to configure, no separate agent to run.

Docker (Quickstart)

docker run -d \
  --name gitness \
  -p 3000:3000 \
  -v /var/lib/gitness:/data \
  harness/gitness:latest

Visit http://your-server:3000, create an admin account, and you are running.

Docker Compose (Production)

services:
  gitness:
    image: harness/gitness:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - gitness_data:/data
    environment:
      GITNESS_PRINCIPAL_ADMIN_EMAIL: [email protected]
      GITNESS_PRINCIPAL_ADMIN_PASSWORD: change-this-password
      GITNESS_URL_BASE: https://git.yourdomain.com
      GITNESS_HTTP_PORT: 3000
      GITNESS_ENCRYPTER_SECRET: generate-a-random-32-char-string
      GITNESS_CI_RESOURCES_PER_REPO: 2

volumes:
  gitness_data:

Reverse Proxy Configuration

Put Gitness behind Caddy or Nginx for HTTPS. A minimal Caddy config:

git.yourdomain.com {
    reverse_proxy localhost:3000
}

Gitness serves both the web UI and Git operations (clone, push, pull) on the same port, so a single reverse proxy entry handles everything.

Like what you're reading? Subscribe to Self-Hosted Weekly — free weekly guides in your inbox.

Repository Management

Gitness supports the standard Git forge workflow:

Branch Protection

Space → Repository → Settings → Rules

Set rules per branch pattern:

Importing Repositories

Gitness can import from external Git URLs:

  1. Create a new repository
  2. Select "Import Repository"
  3. Enter the clone URL
  4. Gitness pulls the full history including all branches and tags

This works for migrating from GitHub, GitLab, Gitea, or any accessible Git remote.

Pipeline Configuration

This is where Gitness shines. Pipelines are defined in .harness/ directory as YAML files, using a syntax that will feel familiar to anyone who has used Drone CI.

Basic Pipeline

Create .harness/build.yaml in your repository:

kind: pipeline
spec:
  stages:
    - type: ci
      spec:
        steps:
          - name: test
            type: run
            spec:
              container: node:20-alpine
              script: |
                npm ci
                npm test

          - name: lint
            type: run
            spec:
              container: node:20-alpine
              script: |
                npm ci
                npm run lint

Push to the repository and the pipeline triggers automatically.

Parallel Steps

Steps within a stage run sequentially by default. Use the parallel group to run steps concurrently:

kind: pipeline
spec:
  stages:
    - type: ci
      spec:
        steps:
          - name: install
            type: run
            spec:
              container: node:20-alpine
              script: npm ci

          - type: parallel
            spec:
              steps:
                - name: test
                  type: run
                  spec:
                    container: node:20-alpine
                    script: npm test

                - name: lint
                  type: run
                  spec:
                    container: node:20-alpine
                    script: npm run lint

Multi-Stage Pipelines

Separate build, test, and deploy into stages that run sequentially:

kind: pipeline
spec:
  stages:
    - type: ci
      name: build-and-test
      spec:
        steps:
          - name: build
            type: run
            spec:
              container: node:20-alpine
              script: |
                npm ci
                npm run build

          - name: test
            type: run
            spec:
              container: node:20-alpine
              script: npm test

    - type: ci
      name: deploy
      spec:
        steps:
          - name: deploy-to-production
            type: run
            spec:
              container: alpine
              script: ./deploy.sh
        when:
          branch: main
          event: push

Service Containers

Spin up databases and other services alongside your pipeline:

kind: pipeline
spec:
  stages:
    - type: ci
      spec:
        services:
          - name: postgres
            image: postgres:16-alpine
            environment:
              POSTGRES_DB: testdb
              POSTGRES_USER: test
              POSTGRES_PASSWORD: test

        steps:
          - name: migrate-and-test
            type: run
            spec:
              container: node:20-alpine
              envs:
                DATABASE_URL: postgres://test:test@postgres:5432/testdb
              script: |
                npm ci
                npm run db:migrate
                npm test

Services are accessible by name as a hostname, just like Docker Compose networking.

Secrets Management

Add secrets through the Gitness UI at the space or repository level. Reference them in pipelines:

steps:
  - name: deploy
    type: run
    spec:
      container: alpine
      envs:
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
        SERVER_HOST: ${{ secrets.SERVER_HOST }}
      script: |
        ssh -i "$DEPLOY_KEY" user@"$SERVER_HOST" "./restart.sh"

Secrets are masked in pipeline logs automatically.

Using Drone Plugins

Gitness is compatible with the Drone plugin ecosystem, which includes hundreds of community-maintained Docker images for common CI/CD tasks:

Docker Build and Push

steps:
  - name: build-image
    type: plugin
    spec:
      name: docker
      inputs:
        repo: registry.example.com/myapp
        registry: registry.example.com
        username: ${{ secrets.REGISTRY_USER }}
        password: ${{ secrets.REGISTRY_PASS }}
        tags:
          - latest
          - ${{ build.commit_sha }}

Slack Notification

steps:
  - name: notify
    type: plugin
    spec:
      name: slack
      inputs:
        webhook: ${{ secrets.SLACK_WEBHOOK }}
        channel: deployments
        template: "Build {{build.status}} for {{repo.name}}"

Resource Management

Gitness uses an embedded SQLite database by default. For production:

The embedded runner executes pipeline steps as Docker containers on the same host. For larger teams, this means the Gitness host needs enough resources for both the platform and the builds.

Limitations to Know

Backup

Since Gitness uses an embedded database and stores everything under /data:

# Stop the container first for a consistent backup
docker stop gitness
tar czf gitness-backup-$(date +%F).tar.gz /var/lib/gitness
docker start gitness

For zero-downtime backups, use filesystem snapshots (ZFS, LVM, or Btrfs) on the data volume.

The Bottom Line

Gitness is the simplest path to a self-hosted Git forge with built-in CI/CD. A single container, a single port, and you have both repository hosting and pipeline execution. The Drone heritage shows in the clean pipeline syntax, and compatibility with Drone plugins gives you a practical ecosystem from day one.

If you are currently running Gitea plus a separate CI/CD tool and find the integration overhead annoying, Gitness collapses that into one service. If you need full forge features like issue tracking and a package registry, Gitea or GitLab are still better fits. But for teams that live in their IDE and just need a place to push code and run builds, Gitness does exactly what it needs to and nothing more.

Get free weekly tips in your inbox. Subscribe to Self-Hosted Weekly