Skip to content

Nebula.NET

Linux, macOS & CI

Run the Nebula.NET protector anywhere .NET runs. Install the cross-platform `nebula` dotnet tool on Linux, macOS or Windows, use it in containers, and drop it into GitHub Actions, GitLab CI or Azure Pipelines.

Nebula.NET’s protector is a cross-platform dotnet tool. The IL rewriting that does the actual protection — renaming, control-flow obfuscation, string/constant/resource/method encryption, reference obfuscation, anti-tamper and metadata hardening — runs on Windows, Linux and macOS wherever .NET 8+ is installed. That makes the same obfuscation you run locally reproducible on a Linux build agent or inside a container, with no Windows machine in the pipeline.

New in 1.1.3. The nebula command is published to nuget.org as a dotnet tool, so Linux and CI no longer need the Windows installer.

What runs where

CapabilityWindowsLinux / macOS
All IL transforms (rename, control flow, encryption, proxy refs, anti-tamper, metadata hardening)✓✓
Strong-name signing✓✓
MSBuild / CLI integration✓✓
Authenticode signing (signAuthenticode)✓— Windows only
Desktop GUI, .msi installer✓— Windows only

Only Authenticode signing is Windows-only — it uses the Windows signing stack. Everything required to protect an assembly works cross-platform. A common pattern is to obfuscate on a Linux agent and do the Authenticode step on a separate Windows signing job (or your existing code-signing service).

Install the tool

Install globally (adds nebula to your PATH):

dotnet tool install --global Delta1Labs.Nebula.Tool
nebula --version

Or pin it per-repository as a local tool so every developer and CI agent uses the same version — this is the recommended approach for CI:

dotnet new tool-manifest          # once, creates .config/dotnet-tools.json
dotnet tool install Delta1Labs.Nebula.Tool
dotnet tool restore               # on CI, restores the pinned version
dotnet tool run nebula --version

The package id is Delta1Labs.Nebula.Tool; the installed command is nebula.

Run it

The CLI takes a JSON config and protects the assemblies it names (or the ones you pass with -i):

nebula --config nebula.json
# or drive a shared settings-only config with an explicit input:
nebula --config nebula.ci.json -i ./publish/MyApp.dll -o ./protected

On build servers, turn on the fail-closed switch so a missing or revoked license breaks the build instead of silently shipping readable code, and license only the build agent(s):

{ "requireLicensedEdition": true, "controlFlowObfuscation": true, "encryptStrings": true }

See the CLI reference for every option and configuration for the full schema.

Containers

The tool installs into any image that has the .NET SDK. Install it into the official SDK image and you have a reusable protector image:

FROM mcr.microsoft.com/dotnet/sdk:8.0
RUN dotnet tool install --global Delta1Labs.Nebula.Tool
ENV PATH="${PATH}:/root/.dotnet/tools"
ENTRYPOINT ["nebula"]

Build and run it over a mounted output folder:

docker build -t my-nebula .
docker run --rm -v "$PWD/publish:/work" my-nebula --config /work/nebula.json

Pin the package version in the dotnet tool install line (for example --version 1.1.4) so the image is reproducible.

GitHub Actions

jobs:
  protect:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0.x'
      - run: dotnet publish -c Release -o publish
      - run: dotnet tool install --global Delta1Labs.Nebula.Tool
      - name: Obfuscate
        run: nebula --config nebula.json -i publish/MyApp.dll -o protected
        env:
          NEBULA_LICENSE_KEY: ${{ secrets.NEBULA_LICENSE_KEY }}
      - uses: actions/upload-artifact@v4
        with:
          name: protected
          path: protected

Put your license key in a repository or organization secret (here NEBULA_LICENSE_KEY) — never in the config file or the repo.

GitLab CI

protect:
  image: mcr.microsoft.com/dotnet/sdk:8.0
  variables:
    PATH: "$PATH:/root/.dotnet/tools"
  script:
    - dotnet publish -c Release -o publish
    - dotnet tool install --global Delta1Labs.Nebula.Tool
    - nebula --config nebula.json -i publish/MyApp.dll -o protected
  artifacts:
    paths:
      - protected/

Set NEBULA_LICENSE_KEY as a masked, protected CI/CD variable in the project settings.

Azure Pipelines

pool:
  vmImage: ubuntu-latest
steps:
  - task: UseDotNet@2
    inputs:
      version: '8.0.x'
  - script: dotnet publish -c Release -o publish
    displayName: Publish
  - script: dotnet tool install --global Delta1Labs.Nebula.Tool
    displayName: Install Nebula
  - script: nebula --config nebula.json -i publish/MyApp.dll -o protected
    displayName: Obfuscate
    env:
      NEBULA_LICENSE_KEY: $(NEBULA_LICENSE_KEY)
  - publish: protected
    artifact: protected

Pipeline order

Obfuscation rewrites IL, so it must run before any signing — sign first and you invalidate both the Authenticode signature and Nebula’s own anti-tamper hash. The full release order and the signing/attestation steps are in Hardening your CI/CD pipeline.

MSBuild instead of the CLI

If you’d rather protect as part of dotnet build without a separate step, the MSBuild integration works the same on Linux and CI — see MSBuild & CI.