compose2nix

repository·main·Indexed 21 days ago

https://github.com/aksiksi/compose2nix

A tool that automatically converts Docker Compose project definitions into native NixOS configurations. It maps Compose services to oci-container configurations and manages networks and volumes via systemd services. It supports integrations with agenix and sops-nix for secret management, Nvidia GPU support via CDI, and provides granular control over systemd options through Docker Compose labels.

Tokens
10.1K
Snippets
32
Records
38
Agent score
66%

What's inside compose2nix

  1. Configure Build spec and Auto-build

    main

    compose2nix supports the Compose build spec.

    • Default behavior: A one-shot systemd service is generated for each container build. You must manually start this service to build the image before the container can run:
      sudo systemctl start podman-build-my-service.service
    - **Auto-build**: If you run `compose2nix` with the `-build=true` flag, the build service is marked as a dependency for the container service. This ensures the build runs automatically before the container starts. 
    
    **Warning**: Using `-build=true` means the build will be re-run on every restart of the root target or the system, which may update the image.
    

    Manual build

    sudo systemctl start podman-build-my-service.service

    CLI flag for auto-build

    compose2nix -build=true

  2. Configure systemd options via Docker Compose labels

    main

    You can extend the generated systemd services by providing additional systemd service and unit options directly within your Docker Compose file using labels.

    Use the compose2nix.systemd. prefix for these labels to pass configuration through to the generated NixOS systemd units.

  3. Manage Podman/Docker services via systemd

    main

    Once generated, you can manage your containers using standard systemctl commands. Replace podman with docker if using the Docker runtime, and myproject-myservice with your actual project and service names.

    Common Tasks

    • List all services: sudo systemctl list-units podman-*
    • List services in a specific project: sudo systemctl list-units *myservice*
    • Restart a service: sudo systemctl restart podman-myproject-myservice.service (Note: if container_name is set in Compose, the project name prefix may be omitted).
    • Stop all resources (Compose Down): sudo systemctl stop podman-compose-myservice-root.target
    • Start all resources (Compose Up): sudo systemctl start podman-compose-myservice-root.target

    Updating Containers (Podman)

    1. Pull the latest image (requires jq):
      sudo podman pull $(sudo podman inspect myproject-myservice | jq -r .[0].ImageName)
    2. Restart the service:
       ```bash
    sudo systemctl restart podman-myproject-myservice.service
    # List services
    sudo systemctl list-units podman-*
    
    # Restart a service
    sudo systemctl restart podman-myproject-myservice.service
    
    # Stop everything
    sudo systemctl stop podman-compose-myservice-root.target
  4. Update secrets in the sops integration test

    main

    To update secrets within the nixos-test/sops directory, use sops edit inside a nix-shell environment with the SOPS_AGE_KEY_FILE environment variable pointing to your age key file. This allows you to edit secrets.yaml using your system's preferred editor while ensuring the sops dependency is available.

    cd nixos-test/sops
    nix-shell -p sops --run "SOPS_AGE_KEY_FILE=age-key.txt sops edit secrets.yaml"
  5. Configure Nvidia GPU support via CDI

    main

    To use Nvidia GPUs in your generated NixOS configuration:

    1. Enable CDI support in your NixOS config:
      hardware.nvidia-container-toolkit.enable = true;
    2. For Docker users: Ensure you are using Docker 25+:
      virtualisation.docker.package = pkgs.docker_25;
    3. In your Compose file, pass CDI devices using devices or deploy. If using Podman, you must set security_opt: [label=disable].
    services:
      myservice:
        devices:
          - nvidia.com/gpu=all
        # OR
        deploy:
          resources:
            reservations:
              devices:
                - driver: cdi
                  device_ids:
                    - nvidia.com/gpu=all
        security_opt:
          - label=disable
    # NixOS config requirement
    { hardware.nvidia-container-toolkit.enable = true; }
    
    # Compose service example
    services:
      myservice:
        devices:
          - nvidia.com/gpu=all
        security_opt:
          - label=disable
  6. Install compose2nix

    main

    You can install compose2nix using several methods:

    1. Nix shell: Run it without permanent installation using:
      nix shell github:aksiksi/compose2nix
    2. **Go install**: If you have Go installed:
       ```bash
    go install github.com/aksiksi/compose2nix
    1. Build from source: Clone the repository and use make:
      make build
    nix shell github:aksiksi/compose2nix
    go install github.com/aksiksi/compose2nix
    make build
  7. Install the compose2nix CLI

    main

    You can install or run compose2nix using several methods depending on your workflow:

    Run the latest version directly without permanent installation:

    nix run github:aksiksi/compose2nix -- -h

    To use a specific version or commit:

    # Specific version
    nix run github:aksiksi/compose2nix/v0.3.0 -- -h
    
    # Specific commit
    nix run github:aksiksi/compose2nix/0c38d282d6662fc902fca7ef5b33e889f9e3e59a -- -h

    Using nixpkgs (NixOS Configuration)

    Add the package directly to your system packages:

    environment.systemPackages = [
      pkgs.compose2nix
    ];

    Using Flakes

    Add compose2nix as an input in your flake.nix:

    compose2nix.url = "github:aksiksi/compose2nix";
    compose2nix.inputs.nixpkgs.follows = "nixpkgs";

    To pin to a specific version in your flake:

    compose2nix.url = "github:aksiksi/compose2nix/v0.3.0";

    Then, install the package in your NixOS configuration:

    environment.systemPackages = [
      inputs.compose2nix.packages.x86_64-linux.default
    ];
  8. Configure Auto-start behavior for services

    main

    By default, all generated services are set to start automatically on boot via systemd. You can change this behavior in two ways:

    1. Global setting: Re-generate your Nix configuration using the -auto_start=false CLI flag.
    2. Per-service setting: Add a Compose label to specific services to enable or disable auto-start.
    services:
      my-service:
        labels:
          - "compose2nix.settings.autoStart=false"
    # Disable globally via CLI
    compose2nix -auto_start=false
    
    # Disable per service in docker-compose.yml
    services:
      my-service:
        labels:
          - "compose2nix.settings.autoStart=false"
  9. Integrate with sops-nix secrets

    main

    To reference secrets already configured in your NixOS system via sops-nix, follow these steps:

    1. Add a compose2nix.settings.sops.secrets label to your Compose services with a comma-separated list of secret names.
    2. Run compose2nix and point to your encrypted secrets YAML file using the --sops_file flag.

    This generates a NixOS configuration that appends the sops-nix secret paths to the container's environmentFiles.

    # In your docker-compose.yml
    services:
      webapp:
        image: nginx:latest
        labels:
          - "compose2nix.settings.sops.secrets=example.env,some-folder/example-2.env"
    
    # Run the command
    compose2nix \
      --inputs docker-compose.yml \
      --sops_file ./secrets/secrets.yaml
  10. Convert a Docker Compose project to NixOS config

    main

    To generate a NixOS configuration from an existing Docker Compose project, run the compose2nix command.

    Requirements:

    • The project must either be passed via the -project flag or have its name defined in the top-level name field of the Compose file.
    • By default, the tool searches for docker-compose.yml in the current working directory.

    Output:

    • The generated NixOS configuration is saved to docker-compose.nix by default.

    Mapping Logic:

    • Each YAML service definition is converted into a oci-container configuration.
    • Systemd services are automatically set up to manage networks and volumes defined in the Compose project.
    • Each Compose service maps to a native NixOS-managed systemd service.
    compose2nix -project=myproject
  11. Integrate with agenix secrets

    main

    agenix decrypts secrets into /run/agenix/. To include these in your Nix configuration via compose2nix:

    1. Place secret environment variables in an encrypted file (e.g., my-env-file.env).
    2. Ensure the decrypted file is readable by the user running compose2nix.
    3. Run compose2nix using the --env_files flag and set --include_env_files=true.

    If you want the output Nix config to only contain environment files (and not the container definitions themselves), add the --env_files_only=true flag.

    compose2nix --env_files=/run/agenix/my-env-file.env --include_env_files=true
    # To include ONLY env files:
    compose2nix --env_files=/run/agenix/my-env-file.env --include_env_files=true --env_files_only=true
  12. Configure systemd service dependencies and lifecycle

    main

    The Generator automatically maps Compose dependencies and resource requirements to systemd unit configurations:

    • Service Dependencies: depends_on in Compose is converted to After and Requires directives in the generated systemd units.
    • Network/Volume Dependencies: Non-external networks and volumes are converted into systemd services, and containers will have After, Requires, and (optionally, if UseUpheldBy is enabled) UpheldBy dependencies on them.
    • Bind Mounts: If CheckBindMounts is enabled, the generator verifies the existence of bind mount paths. If CheckSystemdMounts is enabled, it adds RequiresMountsFor to the systemd unit.
    • Restart Policy: The Compose restart policy is parsed and applied to the systemd service configuration.
    • Stop Timeout: The generator can override the systemd TimeoutStopSec to match Docker/Podman defaults (typically 10s) via the DefaultStopTimeout field.