diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 824b4a6..59351eb 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -1,15 +1,27 @@ --- -name: Magic Wormhole Images +name: Debian Images on: push: - branches: [ "main" ] - tags: [ "*" ] + branches: + - main + paths: + - '.github/workflows/docker-image.yml' + - '*/Dockerfile' + - '*/Pipfile*' + - 'mailbox/welcome.motd' pull_request: - branches: [ "main" ] + branches: + - main + paths: + - '.github/workflows/docker-image.yml' + - '*/Dockerfile' + - '*/Pipfile*' + - 'mailbox/welcome.motd' jobs: build: + name: Build images runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/docker-nix.yml b/.github/workflows/docker-nix.yml new file mode 100644 index 0000000..bb6e367 --- /dev/null +++ b/.github/workflows/docker-nix.yml @@ -0,0 +1,67 @@ +--- +name: NixOS Images + +on: + push: + branches: + - main + paths: + - '.github/workflows/docker-nix.yml' + - 'nixpkgs.json' + - '*.nix' + - '*/*.nix' + - 'nix/**' + pull_request: + branches: + - main + paths: + - '.github/workflows/docker-nix.yml' + - 'nixpkgs.json' + - '*.nix' + - '*/*.nix' + - 'nix/**' + +jobs: + build: + name: Build images + runs-on: ubuntu-latest + strategy: + matrix: + target: + - directory: mailbox + image: leastauthority/magic-wormhole-mailbox + - directory: relay + image: leastauthority/magic-wormhole-relay + - directory: wormhole + image: leastauthority/magic-wormhole + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install Nix + uses: cachix/install-nix-action@v20 + with: + nix_path: nixpkgs=channel:nixos-22.11 + + - name: Build image with Nix + run: | + docker load --input $(nix-build ${{ matrix.target.directory }}) + + - name: Get image tag + run: echo "tag=$(docker images "${{ matrix.target.image }}" --format "{{.Tag}}")" >> $GITHUB_ENV + + - name: Extract Python requirements + run: | + docker run --rm -t \ + --entrypoint python \ + -v $(pwd)/nix/helpers:/helpers \ + ${{ matrix.target.image }}:${{ env.tag }} /helpers/requirements-from-nix.py \ + | grep -vE '==[0-9]+(\.[0-9]+){0,2}-dev' \ + > requirements.txt + # The grep above avoids dupplicated requirements from dev!? + + - name: Scan Python requirements + uses: pypa/gh-action-pip-audit@v1.0.0 + with: + inputs: requirements.txt + continue-on-error: true # TODO: comment on PR and run weekly diff --git a/.gitignore b/.gitignore index a09c56d..03a4783 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /.idea +result* diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..2c58e6c --- /dev/null +++ b/default.nix @@ -0,0 +1,7 @@ +{ pkgs ? import ./nixpkgs.nix { } }: +{ + # Build our Docker images + mailbox = pkgs.callPackage ./mailbox { }; + relay = pkgs.callPackage ./relay { }; + wormhole = pkgs.callPackage ./wormhole { }; +} diff --git a/mailbox/default.nix b/mailbox/default.nix new file mode 100644 index 0000000..95f8437 --- /dev/null +++ b/mailbox/default.nix @@ -0,0 +1,19 @@ +{ pkgs ? import ../nixpkgs.nix { } }: +let + # Call our lib to build the image + output = pkgs.callPackage ../nix/lib/docker-image.nix { + pname = "magic-wormhole-mailbox-server"; + iname = "leastauthority/magic-wormhole-mailbox"; + config = { + WorkingDir = "/app"; + Volumes = { "/db" = { }; }; + Cmd = [ + "twist" + "wormhole-mailbox" + "--usage-db=/db/usage-relay.sqlite" + "--blur-usage=3600" + "--channel-db=/db/relay.sqlite" + ]; + }; + }; +in output diff --git a/nix/helpers/requirements-from-nix.py b/nix/helpers/requirements-from-nix.py new file mode 100644 index 0000000..7ae942a --- /dev/null +++ b/nix/helpers/requirements-from-nix.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import os +import re + +# Pattern for Python modules +p = re.compile('python[0-9]+\.[0-9]+-(.+)-([0-9]+(\.[0-9]+){0,2})(-.+)?') + +# Iterate through Nix store +for dir in os.listdir(os.getenv("NIX_STORE_DIR","/nix/store")): + # Remove the fix hash part + pkg = dir[33:] + # Match Python modules + m = p.match(pkg) + # Print as requirement + if m: + name = m.group(1) + version = m.group(2) + suffix = m.group(4) or "" + print('{}=={}{}'.format(name, version, suffix)) diff --git a/nix/lib/docker-image.nix b/nix/lib/docker-image.nix new file mode 100644 index 0000000..3a76018 --- /dev/null +++ b/nix/lib/docker-image.nix @@ -0,0 +1,19 @@ +{ dockerTools, python3, lib, pname, iname ? pname, config ? {} }: +let + # Inject mailbox in the standard Python env + pyenv = python3.buildEnv.override { + extraLibs = [ python3.pkgs.${pname} ]; + ignoreCollisions = true; + }; + # Parse Python package and NixOS versions to tag the image + pkgVersion = python3.pkgs.${pname}.version; + libVersion = lib.lists.flatten (lib.lists.sublist 1 1 (builtins.split "([^.]+)\.([^.]+)\.([^.]+)\.([^.]+)" lib.version)); + nixVersion = builtins.concatStringsSep "." (lib.lists.take 3 libVersion); +in +# Build the image with our custom CMD +dockerTools.buildLayeredImage { + name = iname; + tag = "${pkgVersion}-nixos-${nixVersion}"; + config = config; + contents = [ pyenv ]; +} diff --git a/nixpkgs.json b/nixpkgs.json new file mode 100644 index 0000000..87445ee --- /dev/null +++ b/nixpkgs.json @@ -0,0 +1,5 @@ +{ + "name": "source", + "url": "https://releases.nixos.org/nixos/21.11/nixos-21.11.337975.eabc3821918/nixexprs.tar.xz", + "sha256": "1fq3zz7qfavksdbqvicns7hg61q3hhbxs2ibm818gy629hwkvsvm" +} \ No newline at end of file diff --git a/nixpkgs.nix b/nixpkgs.nix new file mode 100644 index 0000000..a2ee68d --- /dev/null +++ b/nixpkgs.nix @@ -0,0 +1,2 @@ +# Import local nixpkg.json which pins all our Nix packages +import (builtins.fetchTarball (builtins.fromJSON (builtins.readFile ./nixpkgs.json))) diff --git a/relay/default.nix b/relay/default.nix new file mode 100644 index 0000000..e8d7cc1 --- /dev/null +++ b/relay/default.nix @@ -0,0 +1,19 @@ +{ pkgs ? import ../nixpkgs.nix { } }: +let + output = pkgs.callPackage ../nix/lib/docker-image.nix { + pname = "magic-wormhole-transit-relay"; + iname = "leastauthority/magic-wormhole-relay"; + config = { + WorkingDir = "/app"; + Volumes = { "/db" = { }; }; + Cmd = [ + "twist" + "transitrelay" + "--usage-db=/db/usage-transitrelay.sqlite" + "--blur-usage=3600" + "--port=tcp:4001" + "--websocket=tcp:4002" + ]; + }; + }; +in output diff --git a/wormhole/default.nix b/wormhole/default.nix new file mode 100644 index 0000000..a6aff79 --- /dev/null +++ b/wormhole/default.nix @@ -0,0 +1,14 @@ +{ pkgs ? import ../nixpkgs.nix { } }: +let + # Call our lib to build the image + output = pkgs.callPackage ../nix/lib/docker-image.nix { + pname = "magic-wormhole"; + iname = "leastauthority/magic-wormhole"; + config = { + WorkingDir = "/app"; + EntryPoint = [ + "wormhole" + ]; + }; + }; +in output