{"id":14517331,"url":"https://github.com/aksiksi/compose2nix","last_synced_at":"2025-05-15T20:04:50.898Z","repository":{"id":204798489,"uuid":"712686667","full_name":"aksiksi/compose2nix","owner":"aksiksi","description":"Generate a NixOS config from a Docker Compose project.","archived":false,"fork":false,"pushed_at":"2025-03-16T05:48:11.000Z","size":485,"stargazers_count":566,"open_issues_count":13,"forks_count":8,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-05-14T01:06:28.136Z","etag":null,"topics":["containers","docker","docker-compose","nix","nixos","podman","podman-compose"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aksiksi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-01T01:22:49.000Z","updated_at":"2025-05-11T18:25:52.000Z","dependencies_parsed_at":"2023-11-10T23:21:46.520Z","dependency_job_id":"0fbf7c14-d3b8-4218-b9cd-d02f3b856bad","html_url":"https://github.com/aksiksi/compose2nix","commit_stats":{"total_commits":225,"total_committers":4,"mean_commits":56.25,"dds":"0.45333333333333337","last_synced_commit":"07cad037b8887ba94cd7236ffd1a8ee47002a9fe"},"previous_names":["aksiksi/compose2nixos","aksiksi/nixose","aksiksi/nix-compose","aksiksi/compose2nix"],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aksiksi%2Fcompose2nix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aksiksi%2Fcompose2nix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aksiksi%2Fcompose2nix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aksiksi%2Fcompose2nix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aksiksi","download_url":"https://codeload.github.com/aksiksi/compose2nix/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414499,"owners_count":22067272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["containers","docker","docker-compose","nix","nixos","podman","podman-compose"],"created_at":"2024-09-04T03:01:09.581Z","updated_at":"2025-05-15T20:04:48.710Z","avatar_url":"https://github.com/aksiksi.png","language":"Go","funding_links":[],"categories":["Go","docker","Development"],"sub_categories":["Discovery"],"readme":"# compose2nix\n\n[![Test](https://github.com/aksiksi/compose2nix/actions/workflows/test.yml/badge.svg)](https://github.com/aksiksi/compose2nix/actions/workflows/test.yml)\n[![NixOS](https://github.com/aksiksi/compose2nix/actions/workflows/nixos.yml/badge.svg)](https://github.com/aksiksi/compose2nix/actions/workflows/nixos.yml)\n[![codecov](https://codecov.io/gh/aksiksi/compose2nix/graph/badge.svg)](https://codecov.io/gh/aksiksi/compose2nix)\n[![Go Reference](https://pkg.go.dev/badge/github.com/aksiksi/compose2nix.svg)](https://pkg.go.dev/github.com/aksiksi/compose2nix)\n\nA tool to automatically generate a NixOS config from a Docker Compose project.\n\n## Overview\n\n### Intro video\n\n[![Rambly introduction video](https://img.youtube.com/vi/hCAFyzJ81Pg/hqdefault.jpg)](https://youtu.be/hCAFyzJ81Pg)\n\n### Why?\n\nRunning a Docker Compose stack/project on NixOS is not well supported. One approach is to define a systemd service that runs `docker-compose up` on start and `docker compose down` on stop.\n\nBut with this approach, changes to individual services are not visible to NixOS, which means that NixOS will need to restart the systemd service on **any** change to the Compose file. This can be mitigated by defining a systemd reload handler, but it still is finicky to work with and will always remain opaque to NixOS.\n\nTo top it all off, using Docker Compose on NixOS is fairly redundant as the features you get with Compose are available natively on NixOS.\n\n### How?\n\n`compose2nix` takes your existing Docker Compose file(s) and converts each YAML service definition into a [`oci-container`](https://search.nixos.org/options?query=virtualisation.oci-containers) config. The tool also sets up systemd services to create all networks and volumes that are part of the Compose project. Since `compose2nix` uses the same library that the Docker CLI relies on under the hood, you also get Compose file validation and syntax checking \"for free\".\n\n### Benefits\n\n1. Supports both Docker and Podman out of the box.\n2. Each Compose service maps into a systemd service that is natively managed by NixOS.\n3. A change to one container service only impacts that container and any of its dependents.\n4. Generated systemd services can be extended from your NixOS config.\n5. `compose2nix` supports setting additional systemd service and unit options through Docker Compose labels (search for the `compose2nix.systemd.` label in the samples).\n\n## Quickstart\n\nInstall the `compose2nix` CLI via one of the following methods:\n\n1. Run using `nix run` (**recommended**):\n    ```\n    # Latest\n    nix run github:aksiksi/compose2nix -- -h\n\n    # Specific version\n    nix run github:aksiksi/compose2nix/v0.3.0 -- -h\n\n    # Specific commit\n    nix run github:aksiksi/compose2nix/0c38d282d6662fc902fca7ef5b33e889f9e3e59a -- -h\n    ```\n2. Install from `nixpkgs`:\n    ```\n    # NixOS config\n    environment.systemPackages = [\n      pkgs.compose2nix\n    ];\n    ```\n3. Add the following to your `flake.nix`:\n    ```nix\n    compose2nix.url = \"github:aksiksi/compose2nix\";\n    compose2nix.inputs.nixpkgs.follows = \"nixpkgs\";\n    ```\n\n    Optionally, you can pin to a specific version:\n    ```nix\n    compose2nix.url = \"github:aksiksi/compose2nix/v0.3.0\";\n    ```\n\n    You can then install the package by adding the following to your NixOS config:\n    ```nix\n    environment.systemPackages = [\n      inputs.compose2nix.packages.x86_64-linux.default\n    ];\n    ```\n\nRun `compose2nix`. Note that project must either be passed in **or** set in the Compose file's top-level \"name\".\n\n```bash\ncompose2nix -project=myproject\n```\n\nBy default, the tool looks for `docker-compose.yml` in the **current directory** and outputs the NixOS config to `docker-compose.nix`.\n\n## Roadmap\n\n- [x] Basic implementation\n- [x] Support for most common Docker Compose features\n- [x] Support for using secret environment files\n\n## Docs\n\n### Sample\n\n* Input: https://github.com/aksiksi/compose2nix/blob/main/testdata/compose.yml\n* Output (Docker): https://github.com/aksiksi/compose2nix/blob/main/testdata/TestBasic.docker.nix\n* Output (Podman): https://github.com/aksiksi/compose2nix/blob/main/testdata/TestBasic.podman.nix\n\n### Working with Secrets\n\n#### [agenix](https://github.com/ryantm/agenix)\n\n`agenix` works by decrypting secrets and placing them in `/run/agenix/`. To feed this into your Nix config:\n\n1. Place all secret env variables in the encrypted env file (e.g., `my-env-file.env`).\n2. Mark the decrypted env file as readable by the user running `compose2nix`.\n3. Run `compose2nix` with the env file path(s) and set `-include_env_files=true`:\n\n   ```\n   compose2nix --env_files=/run/agenix/my-env-file.env --include_env_files=true\n   ```\n\n\u003e [!NOTE]\n\u003e If you also want to ensure that you only include env files in the output Nix config, set `-env_files_only=true`.\n\n### Patterns\n\nIn this case, the project is called `myproject` and the service name is `myservice`. Replace `podman` with `docker` if using the Docker runtime.\n\n#### List all services\n\n```\nsudo systemctl list-units podman-*\n```\n\n#### List all services in a project\n\n```\nsudo systemctl list-units *myservice*\n```\n\n#### Restart a service\n\nNote: if the Compose service has a `container_name` set, then the systemd service will not include the project name.\n\n```\nsudo systemctl restart podman-myproject-myservice.service\n```\n\n#### Update a Container\n\n1. Pull the latest image for the container (requires [`jq`](https://jqlang.github.io/jq/)):\n\n```\nsudo podman pull $(sudo podman inspect myproject-myservice | jq -r .[0].ImageName)\n```\n\n2. Restart the service:\n\n```\nsudo systemctl restart podman-myproject-myservice.service\n```\n\n#### **Podman**: Auto-update containers\n\n1. Add a `io.containers.autoupdate=registry` label to each Compose service you want to have auto-updated.\n    * Make sure to use a **fully-qualified** image path (e.g., `docker.io/repo/image`). Otherwise, Podman will fail to start the container.\n2. Run `sudo podman auto-update --dry-run` to see which containers would get updated. Omit `--dry-run` to update \u0026 restart services.\n\nYou can optionally enable a Podman-provided timer that runs the command above once per day at midnight (by default):\n\n```nix\n# Enable the existing timer unit.\nsystemd.timers.\"podman-auto-update\".wantedBy = [ \"timers.target\" ];\n```\n\nSee this page for details: https://docs.podman.io/en/latest/markdown/podman-auto-update.1.html\n\n#### Auto-start services on boot\n\nBy default, all generated services will be started by systemd on boot.\n\nYou can override this behavior in two different ways:\n\n1. **Disable auto-start for all services:** Re-generate your config with `-auto_start=false`.\n2. **Disable or enable auto-start for a single service:** Add a Compose label to your service like this:\n\n    ```yaml\n    services:\n      my-service:\n        labels:\n          # Enable\n          - \"compose2nix.settings.autoStart=true\"\n          # Disable\n          - \"compose2nix.settings.autoStart=false\"\n    ```\n\n#### `docker compose down`\n\nBy default, this will only remove networks.\n\n```\nsudo systemctl stop podman-compose-myservice-root.target\n```\n\n##### Remove volumes\n\nYou can do one of the following:\n\n1. Re-generate your NixOS config with: `-remove_volumes=true`\n2. Run `sudo podman volume prune` to manually cleanup unreferenced volumes\n\n#### `docker compose up`\n\n```\nsudo systemctl start podman-compose-myservice-root.target\n```\n\n#### Compose Build spec\n\n`compose2nix` has basic support for the Build spec. See [Supported Compose Features] below for details.\n\nBy default, a systemd service will be generated for _each_ container build. This is a\none-shot service that simply runs the build when started.\n\nFor example, if you have a service named `my-service` with a `build` set:\n\n```\nsudo systemctl start podman-build-my-service.service\n```\n\nNote that, until this is run, the container for `my-service` will **not be able to start** due to the missing image.\n\n##### Auto-build\n\nIf you run the CLI with `-build=true`, the systemd service will be marked as a dependency for the service\ncontainer. This means that the build will be run before the container is started.\n\nHowever, it is important to note that the build will be re-run on every restart of the root target or system.\nThis will result in the build image being updated (potentially).\n\n### Nvidia GPU Support\n\n1. Enable CDI support in your NixOS config:\n\n```nix\n{\n  hardware.nvidia-container-toolkit.enable = true;\n}\n```\n\n**Docker only:**\n\nMake sure you are running Docker 25+:\n\n```nix\n{\n  virtualisation.docker.package = pkgs.docker_25;\n}\n```\n\n2. Pass in CDI devices via either `devices` **or** `deploy` (both map to the same thing under the hood):\n\n```yaml\nservices:\n  myservice:\n    # ... other fields\n\n    # Option 1\n    devices:\n      - nvidia.com/gpu=all\n    # Option 2\n    deploy:\n      resources:\n        reservations:\n          devices:\n            # Driver must be set to \"cdi\" - all others are ignored.\n            - driver: cdi\n              device_ids:\n                - nvidia.com/gpu=all\n\n    # Required for Podman.\n    security_opt:\n      - label=disable\n```\n\n### NixOS Version Support Policy\n\nI always aim to support the **latest** stable version of NixOS (24.05 at the\ntime of writing). As a result, some NixOS unstable options are not used.\n\nIf the option has a strong usecase, I am open to adding a CLI flag that can be\ndeprecated once the option is stable.\n\n### Known Issues\n\n#### Manually stopping containers with UpheldBy\n\nsystemd does not differentiate between a manual unit stop and a unit stopped due\nto a failure (i.e., in failed state). This means that if you stop a unit, it\nwill automatically be started by the service(s) it depends on.\n\nSuppose you have the following Compose file:\n\n```yaml\nservices:\n  app:\n    image: myname/app\n    depends_on:\n      - db\n  db:\n    image: postgres\n```\n\nIf you *manually stop* the `app` systemd unit, the `db` unit will\n**automatically* restart it due to the `UpheldBy` setting.\n\nDiscussion with the systemd team: https://github.com/systemd/systemd/issues/35636\n\n#### Docker \u0026 multiple networks\n\nIf you are using the Docker runtime and a Compose service connects to multiple networks, you'll need to use v25+. Otherwise, the container service will fail to start.\n\nYou can pin the Docker version to v25 like so:\n\n```nix\n{\n  virtualisation.docker.package = pkgs.docker_25;\n}\n```\n\nDiscussion: https://github.com/aksiksi/compose2nix/issues/24\n\n#### Podman: Port forwarding in `internal` networks\n\nFor some reason, when you run a *rootful* Podman container in a network that is marked as `internal`, port forwarding to the host does not work. Podman seems to completely isolate the network from the external world - including the host network! Note that Docker claims to support this behavior out-of-the-box ([ref](https://docs.docker.com/reference/cli/docker/network/create/#internal)).\n\nThere is a workaround: remove the `internal` setting and set the network driver option `no_default_route=1` ([example](https://github.com/aksiksi/compose2nix/discussions/39#discussioncomment-10717015)).\n\n```yaml\nnetworks:\n  my-network:\n    driver: bridge\n    driver_opts:\n      no_default_route: 1 # \u003c\u003c\u003c This is what prevents external network access.\n    ipam:\n      config:\n        - subnet: 10.8.1.0/24\n          gateway: 10.8.1.0\n```\n\nThis will allow you to connect from the host, while also preventing internet access from within the container. \n\nThis is where the check is done in Netavark: [link](https://github.com/containers/netavark/blob/cebebc70daec7010c4005798a7958b3b6be7151d/src/network/bridge.rs#L756)\n\n### Usage\n\n```\n$ compose2nix -h\nUsage of compose2nix:\n  -auto_format\n    \tif true, Nix output will be formatted using \"nixfmt\" (must be present in $PATH).\n  -auto_start\n    \tauto-start setting for generated service(s). this applies to all services, not just containers. (default true)\n  -check_systemd_mounts\n    \tif set, volume paths will be checked against systemd mount paths on the current machine and marked as container dependencies.\n  -create_root_target\n    \tif set, a root systemd target will be created, which when stopped tears down all resources. (default true)\n  -default_stop_timeout duration\n    \tdefault stop timeout for generated container services. (default 1m30s)\n  -env_files string\n    \tone or more comma-separated paths to .env file(s).\n  -env_files_only\n    \tonly use env file(s) in the NixOS container definitions.\n  -generate_unused_resources\n    \tif set, unused resources (e.g., networks) will be generated even if no containers use them.\n  -ignore_missing_env_files\n    \tif set, missing env files will be ignored.\n  -include_env_files\n    \tinclude env files in the NixOS container definition.\n  -inputs string\n    \tone or more comma-separated path(s) to Compose file(s). (default \"docker-compose.yml\")\n  -output string\n    \tpath to output Nix file. (default \"docker-compose.nix\")\n  -project string\n    \tproject name used as a prefix for generated resources. this overrides any top-level \"name\" set in the Compose file(s).\n  -remove_volumes\n    \tif set, volumes will be removed on systemd service stop.\n  -root_path string\n    \troot path to use for any relative paths in the Compose file (e.g., volumes). if unset, the current working directory will be used.\n  -runtime string\n    \tone of: [\"podman\", \"docker\"]. (default \"podman\")\n  -service_include string\n    \tregex pattern for services to include.\n  -use_compose_log_driver\n    \tif set, always use the Docker Compose log driver.\n  -use_upheld_by\n    \tif set, upheldBy will be used for service dependencies (NixOS 24.05+).\n  -version\n    \tdisplay version and exit\n  -write_nix_setup\n    \tif true, Nix setup code is written to output (runtime, DNS, autoprune, etc.) (default true)\n```\n\n### Supported Compose Features\n\nIf a feature is missing, please feel free to [create an issue](https://github.com/aksiksi/compose2nix/issues/new). In theory, any Compose feature can be supported because `compose2nix` uses the same library as the Docker CLI under the hood.\n\n#### [`services`](https://docs.docker.com/compose/compose-file/05-services/)\n\n|   |     | Notes |\n|---|:---:|-------|\n| [`image`](https://docs.docker.com/compose/compose-file/05-services/#image) | ✅ | |\n| [`container_name`](https://docs.docker.com/compose/compose-file/05-services/#container_name) | ✅ | |\n| [`environment`](https://docs.docker.com/compose/compose-file/05-services/#environment) | ✅ | |\n| [`env_file`](https://docs.docker.com/compose/compose-file/05-services/#env_file) | ✅ | |\n| [`volumes`](https://docs.docker.com/compose/compose-file/05-services/#volumes) | ✅ | |\n| [`labels`](https://docs.docker.com/compose/compose-file/05-services/#labels) | ✅ | |\n| [`ports`](https://docs.docker.com/compose/compose-file/05-services/#ports) | ✅ | |\n| [`dns`](https://docs.docker.com/compose/compose-file/05-services/#dns) | ✅ | |\n| [`cap_add/cap_drop`](https://docs.docker.com/compose/compose-file/05-services/#cap_add) | ✅ | |\n| [`logging`](https://docs.docker.com/compose/compose-file/05-services/#logging) | ✅ | |\n| [`depends_on`](https://docs.docker.com/compose/compose-file/05-services/#depends_on) | ⚠️  | Only short syntax is supported. |\n| [`restart`](https://docs.docker.com/compose/compose-file/05-services/#restart) | ✅ | |\n| [`deploy.restart_policy`](https://docs.docker.com/compose/compose-file/deploy/#restart_policy) | ✅ | |\n| [`deploy.resources.limits`](https://docs.docker.com/compose/compose-file/deploy/#resources) | ✅ | |\n| [`deploy.resources.reservations.cpus`](https://docs.docker.com/compose/compose-file/deploy/#cpus) | ✅ | |\n| [`deploy.resources.reservations.memory`](https://docs.docker.com/compose/compose-file/deploy/#memory) | ✅ | |\n| [`deploy.resources.reservations.devices`](https://docs.docker.com/compose/compose-file/deploy/#devices) | ⚠️  | Only CDI driver is supported. |\n| [`devices`](https://docs.docker.com/compose/compose-file/05-services/#devices) | ✅ | |\n| [`networks.aliases`](https://docs.docker.com/compose/compose-file/05-services/#aliases) | ✅ | |\n| [`networks.ipv*_address`](https://docs.docker.com/compose/compose-file/05-services/#ipv4_address-ipv6_address) | ✅ | |\n| [`network_mode`](https://docs.docker.com/compose/compose-file/05-services/#network_mode) | ✅ | |\n| [`privileged`](https://docs.docker.com/compose/compose-file/05-services/#privileged) | ✅ | |\n| [`extra_hosts`](https://docs.docker.com/compose/compose-file/05-services/#extra_hosts) | ✅ | |\n| [`sysctls`](https://docs.docker.com/compose/compose-file/05-services/#sysctls) | ✅ | |\n| [`shm_size`](https://docs.docker.com/compose/compose-file/05-services/#shm_size) | ✅ | |\n| [`runtime`](https://docs.docker.com/compose/compose-file/05-services/#runtime) | ✅ | |\n| [`security_opt`](https://docs.docker.com/compose/compose-file/05-services/#security_opt) | ✅ | |\n| [`command`](https://docs.docker.com/compose/compose-file/05-services/#command) | ✅ | |\n| [`entrypoint`](https://docs.docker.com/compose/compose-file/05-services/#entrypoint) | ✅ | |\n| [`healthcheck`](https://docs.docker.com/compose/compose-file/05-services/#healthcheck) | ✅ | |\n| [`hostname`](https://docs.docker.com/compose/compose-file/05-services/#hostname) | ✅ | |\n| [`mac_address`](https://docs.docker.com/compose/compose-file/05-services/#mac_address) | ✅ | |\n| [`user`](https://docs.docker.com/compose/compose-file/05-services/#user) | ✅ | |\n\n#### [`networks`](https://docs.docker.com/compose/compose-file/06-networks/)\n\n|   |     |\n|---|:---:|\n| [`labels`](https://docs.docker.com/compose/compose-file/06-networks/#labels) | ✅ |\n| [`name`](https://docs.docker.com/compose/compose-file/06-networks/#name) | ✅ |\n| [`driver`](https://docs.docker.com/compose/compose-file/06-networks/#driver) | ✅ |\n| [`driver_opts`](https://docs.docker.com/compose/compose-file/06-networks/#driver_opts) | ✅ |\n| [`enable_ipv6`](https://docs.docker.com/compose/compose-file/06-networks/#enable_ipv6) | ✅ |\n| [`ipam`](https://docs.docker.com/compose/compose-file/06-networks/#ipam) | ✅ |\n| [`external`](https://docs.docker.com/compose/compose-file/06-networks/#external) | ✅ |\n| [`internal`](https://docs.docker.com/compose/compose-file/06-networks/#internal) | ✅ |\n\n#### [`volumes`](https://docs.docker.com/compose/compose-file/07-volumes/)\n\n|   |     |\n|---|:---:|\n| [`driver`](https://docs.docker.com/compose/compose-file/07-volumes/#driver) | ✅ |\n| [`driver_opts`](https://docs.docker.com/compose/compose-file/07-volumes/#driver_opts) | ✅ |\n| [`labels`](https://docs.docker.com/compose/compose-file/07-volumes/#labels) | ✅ |\n| [`name`](https://docs.docker.com/compose/compose-file/07-volumes/#name) | ✅ |\n| [`external`](https://docs.docker.com/compose/compose-file/07-volumes/#external) | ✅ |\n\n#### [`build`](https://docs.docker.com/reference/compose-file/build/)\n\n|   |     | Notes |\n|---|:---:|-------|\n| [`args`](https://docs.docker.com/reference/compose-file/build/#args) | ✅ | |\n| [`tags`](https://docs.docker.com/reference/compose-file/build/#tags) | ✅ |\n| [`context`](https://docs.docker.com/reference/compose-file/build/#context) | ⚠️  | Git repo is not supported |\n| [`network`](https://docs.docker.com/reference/compose-file/build/#network) | ❌ |\n| [`image`+`build`](https://docs.docker.com/reference/compose-file/build/#using-build-and-image) | ❌ |\n\n#### Misc\n\n* [`name`](https://docs.docker.com/compose/compose-file/04-version-and-name/#name-top-level-element) - ✅\n\n### Alternative Installation Methods\n\n1. Use in a Nix shell:\n    ```bash\n    nix shell github:aksiksi/compose2nix\n    ```\n2. Install the command using `go`:\n    ```\n    go install github.com/aksiksi/compose2nix\n    ```\n3. Clone this repo and run `make build`.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faksiksi%2Fcompose2nix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faksiksi%2Fcompose2nix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faksiksi%2Fcompose2nix/lists"}