diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8e688557e1b21698fee3e617dbb992cd3963d10e..024703837471b709b59c3eab68e936ac5f0587c9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,7 +3,7 @@ variables:
   DOCKER_REV: "853f348f9caf38b08740b280296fbd34e09abb3a"
 
   GHC_VERSION: 8.10.7
-  CABAL_INSTALL_VERSION: 3.2.0.0
+  CABAL_INSTALL_VERSION: 3.4.0.0
 
 workflow:
   rules:
@@ -23,12 +23,18 @@ workflow:
 
 build-aarch64-linux-deb10:
   extends: .build
+  before_script:
+    - sudo apt-get update -y
+    - sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget lsb-release software-properties-common gnupg2 apt-transport-https
   tags:
     - aarch64-linux
   image: "registry.gitlab.haskell.org/ghc/ci-images/aarch64-linux-deb10:$DOCKER_REV"
 
 build-armv7-linux-deb10:
   extends: .build
+  before_script:
+    - sudo apt-get update -y
+    - sudo apt-get install -y libnuma-dev zlib1g-dev libgmp-dev libgmp10 libssl-dev liblzma-dev libbz2-dev git wget lsb-release software-properties-common gnupg2 apt-transport-https
   tags:
     - armv7-linux
   image: "registry.gitlab.haskell.org/ghc/ci-images/armv7-linux-deb10:$DOCKER_REV"
@@ -55,7 +61,32 @@ build-x86_64-darwin:
   tags:
     - x86_64-darwin
 
+build-aarch64-darwin:
+  tags:
+    - aarch64-darwin-m1
+  script: |
+    set -Eeuo pipefail
+    function runInNixShell() {
+      time nix-shell $CI_PROJECT_DIR/.gitlab/shell.nix \
+        -I nixpkgs=https://github.com/angerman/nixpkgs/archive/75f7281738b.tar.gz \
+        --argstr system "aarch64-darwin" \
+        --pure \
+        --keep CI_PROJECT_DIR \
+        --keep MACOSX_DEPLOYMENT_TARGET \
+        --keep GHC_VERSION \
+        --keep CABAL_INSTALL_VERSION \
+        --run "$1" 2>&1
+    }
+    runInNixShell "cabal update && mkdir vendored && cd vendored && cabal unpack network-3.1.2.1 && cd network-3.1.2.1 && autoreconf -fi" 2>&1
+    runInNixShell "./.gitlab/ci.sh" 2>&1
+  variables:
+    MACOSX_DEPLOYMENT_TARGET: "10.7"
+  artifacts:
+    expire_in: 2 week
+    paths:
+      - out
+
 build-x86_64-windows:
   extends: .build
   tags:
-    - new-x86_64-windows
\ No newline at end of file
+    - new-x86_64-windows
diff --git a/.gitlab/ci.sh b/.gitlab/ci.sh
old mode 100644
new mode 100755
index 3f981dbd10c315584389da21dbb7556b6b2e060d..1e90c820d3ab664af5238c928a68522b6736ae0a
--- a/.gitlab/ci.sh
+++ b/.gitlab/ci.sh
@@ -2,110 +2,42 @@
 
 set -Eeuo pipefail
 
-TOP="$(pwd)"
-source "$TOP/.gitlab/common.sh"
+source "$CI_PROJECT_DIR/.gitlab/common.sh"
 
-# We don't have sudo access in GitLab CI, so we can't just dump binaries in
-# the usual PATH locations.
-toolchain="$(pwd)/toolchain"
-mkdir -p "$toolchain/bin"
-export PATH="$toolchain/bin:$PATH"
 
-export CABAL_DIR="$TOP/cabal"
-mkdir -p "$CABAL_DIR"
+export GHCUP_INSTALL_BASE_PREFIX="$CI_PROJECT_DIR/toolchain"
+export CABAL_DIR="$CI_PROJECT_DIR/cabal"
 
-# Platform-specific bits
-MAKE="make"
 case "$(uname)" in
     MSYS_*|MINGW*)
-        CABAL_DIR="$(cygpath -w "$CABAL_DIR")"
-        ;;
-    FreeBSD)
-        MAKE="gmake"
+        export CABAL_DIR="$(cygpath -w "$CABAL_DIR")"
+		GHCUP_BINDIR="${GHCUP_INSTALL_BASE_PREFIX}/ghcup/bin"
         ;;
+	*)
+		GHCUP_BINDIR="${GHCUP_INSTALL_BASE_PREFIX}/.ghcup/bin"
+		;;
 esac
 
-fetch_cabal_install_unix() {
-    local cabal_url="$1"
-    run curl -L -o cabal.tar.xz "$cabal_url"
-    run tar --directory "$toolchain/bin/" -xf cabal.tar.xz cabal
-    chmod +x "$toolchain/bin/cabal"
-    CABAL="$toolchain/bin/cabal"
-}
-
-setup_cabal_install() {
-    if [ -z "${CABAL:-}" ]; then
-        info "Fetching GHC..."
-        case "$(uname)" in
-            FreeBSD)
-                fetch_cabal_install_unix "https://hasufell.de/d/d3e215db133e4fcaa61e/files/?p=/cabal-install-$CABAL_INSTALL_VERSION-x86_64-portbld-freebsd.tar.xz&dl=1" ;;
-            Darwin)
-                fetch_cabal_install_unix "https://downloads.haskell.org/~cabal/cabal-install-$CABAL_INSTALL_VERSION/cabal-install-$CABAL_INSTALL_VERSION-x86_64-apple-darwin17.7.0.tar.xz" ;;
-            MSYS_*|MINGW*)
-                cabal_url="https://downloads.haskell.org/~cabal/cabal-install-$CABAL_INSTALL_VERSION/cabal-install-$CABAL_INSTALL_VERSION-x86_64-unknown-mingw32.zip"
-                run curl -L -o cabal.zip "$cabal_url"
-                run unzip cabal.zip
-                cp cabal.exe "$toolchain/bin/cabal.exe"
-                chmod +x "$toolchain/bin/cabal.exe"
-                CABAL="$toolchain/bin/cabal.exe"
-                ;;
-            *) fail "no cabal-install bindist for $(uname)"
-        esac
-
-    fi
-    export CABAL
-    run "$CABAL" --version
-}
-
-
-fetch_ghc_unix() {
-    local ghc_url="$1"
-    run curl -sSfL -o ghc.tar.xz "$ghc_url"
-    run tar -xf ghc.tar.xz
-
-    pushd "ghc-${GHC_VERSION}"
-    run ./configure --prefix="$toolchain"
-    run "$MAKE" install
-    popd
-    GHC="$toolchain/bin/ghc"
-}
-
-setup_ghc() {
-    if [ -z "${GHC:-}" ]; then
-        info "Fetching GHC..."
-        case "$(uname)" in
-            FreeBSD)
-                fetch_ghc_unix "https://downloads.haskell.org/~ghc/$GHC_VERSION/ghc-$GHC_VERSION-x86_64-unknown-freebsd.tar.xz" ;;
-            Darwin)
-                fetch_ghc_unix "https://downloads.haskell.org/~ghc/$GHC_VERSION/ghc-$GHC_VERSION-x86_64-apple-darwin.tar.xz" ;;
-            MSYS_*|MINGW*)
-                ghc_url="https://downloads.haskell.org/~ghc/$GHC_VERSION/ghc-$GHC_VERSION-x86_64-unknown-mingw32.tar.xz"
-                run curl -sSfL -o ghc.tar.xz "$ghc_url"
-                run tar -xf ghc.tar.xz
-                cp -R ghc-$GHC_VERSION/* "$toolchain"
-                GHC="$toolchain/bin/ghc.exe"
-                run "$GHC" --version
-                GHC="$(cygpath -w $GHC)"
-                return
-                ;;
-            *) fail "no GHC bindist for $(uname)"
-        esac
-    fi
+mkdir -p "$CABAL_DIR"
+mkdir -p "$GHCUP_BINDIR"
+export PATH="$GHCUP_BINDIR:$PATH"
 
-    export GHC
-    run "$GHC" --version
-}
+export BOOTSTRAP_HASKELL_NONINTERACTIVE=1
+export BOOTSTRAP_HASKELL_GHC_VERSION=$GHC_VERSION
+export BOOTSTRAP_HASKELL_CABAL_VERSION=$CABAL_INSTALL_VERSION
+export BOOTSTRAP_HASKELL_VERBOSE=1
+export BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG=yes
 
-setup_cabal_install
-setup_ghc
+curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
 
-run "$CABAL" update
-run "$CABAL" v2-install cabal-install \
-    -w "$GHC" \
-    --installdir="$TOP/out" \
+run cabal v2-install cabal-install \
+    -w "ghc-$GHC_VERSION" \
+    --installdir="$CI_PROJECT_DIR/out" \
     --install-method=copy \
     --overwrite-policy=always \
     --enable-executable-static \
     --disable-profiling \
     --enable-split-sections \
     --enable-executable-stripping
+
+cp dist-newstyle/cache/plan.json "$CI_PROJECT_DIR/out/plan.json"
diff --git a/.gitlab/shell.nix b/.gitlab/shell.nix
new file mode 100644
index 0000000000000000000000000000000000000000..33c7c67beee9cc5d72b393055fb62017336829fb
--- /dev/null
+++ b/.gitlab/shell.nix
@@ -0,0 +1,90 @@
+{ system ? "aarch64-darwin"
+#, nixpkgs ? fetchTarball https://github.com/angerman/nixpkgs/archive/257cb120334.tar.gz #apple-silicon.tar.gz
+, pkgs ? import <nixpkgs> { inherit system; }
+, compiler ? if system == "aarch64-darwin" then "ghc8103Binary" else "ghc8103"
+}: pkgs.mkShell {
+  # this prevents nix from trying to write the env-vars file.
+  # we can't really, as NIX_BUILD_TOP/env-vars is not set.
+  noDumpEnvVars=1;
+
+  # stop polluting LDFLAGS with -liconv
+  dontAddExtraLibs = true;
+
+  # we need to inject ncurses into --with-curses-libraries.
+  # the real fix is to teach terminfo to use libcurses on macOS.
+  # CONFIGURE_ARGS = "--with-intree-gmp --with-curses-libraries=${pkgs.ncurses.out}/lib";
+  CONFIGURE_ARGS = "--with-intree-gmp --with-curses-libraries=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib --with-iconv-includes=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include --with-iconv-libraries=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib SH=/bin/bash";
+
+  # magic speedup pony :facepalm:
+  #
+  # nix has the ugly habbit of duplicating ld flags more than necessary.  This
+  # somewhat consolidates this.
+  shellHook = ''
+  export NIX_LDFLAGS=$(for a in $NIX_LDFLAGS; do echo $a; done |sort|uniq|xargs)
+  export NIX_LDFLAGS_FOR_TARGET=$(for a in $NIX_LDFLAGS_FOR_TARGET; do echo $a; done |sort|uniq|xargs)
+  export NIX_LDFLAGS_FOR_TARGET=$(comm -3 <(for l in $NIX_LDFLAGS_FOR_TARGET; do echo $l; done) <(for l in $NIX_LDFLAGS; do echo $l; done))
+
+
+  # Impurity hack for GHC releases.
+  #################################
+  # We don't want binary releases to depend on nix, thus we'll need to make sure we don't leak in references.
+  # GHC externally depends only on iconv and curses.  However we can't force a specific curses library for
+  # the terminfo package, as such we'll need to make sure we only look in the system path for the curses library
+  # and not pick up the tinfo from the nix provided ncurses package.
+  #
+  # We also need to force us to use the systems COREFOUNDATION, not the one that nix builds. Again this is impure,
+  # but it will allow us to have proper binary distributions.
+  #
+  # do not use nixpkgs provided core foundation
+  export NIX_COREFOUNDATION_RPATH=/System/Library/Frameworks
+  # drop curses from the LDFLAGS, we really want the system ones, not the nix ones.
+  export NIX_LDFLAGS=$(for lib in $NIX_LDFLAGS; do case "$lib" in *curses*);; *) echo -n "$lib ";; esac; done;)
+  export NIX_CFLAGS_COMPILE+=" -Wno-nullability-completeness -Wno-availability -Wno-expansion-to-defined -Wno-builtin-requires-header -Wno-unused-command-line-argument"
+
+  # unconditionally add the MacOSX.sdk and TargetConditional.h
+  export NIX_CFLAGS_COMPILE+=" -isystem /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include"
+  export NIX_LDFLAGS="-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib $NIX_LDFLAGS"
+
+  '';
+
+  nativeBuildInputs = (with pkgs; [
+    # This needs to come *before* ghc,
+    # otherwise we migth end up with the clang from
+    # the bootstrap GHC in PATH with higher priority.
+    clang_11
+    llvm_11
+
+    haskell.compiler.${compiler}
+    haskell.packages.${compiler}.cabal-install
+    haskell.packages.${compiler}.alex
+    haskell.packages.${compiler}.happy # _1_19_12 is needed for older GHCs.
+
+    automake
+    autoconf
+    m4
+
+    gmp
+    zlib.out
+    zlib.dev
+    glibcLocales
+    # locale doesn't build yet :-/
+    # locale
+
+    git
+
+    python3
+    # python3Full
+    # python3Packages.sphinx
+    perl
+
+    which
+    wget
+	curl
+    file
+
+    xz
+    xlibs.lndir
+
+    cacert ])
+  ++ (with pkgs.darwin.apple_sdk.frameworks; [ Foundation Security ]);
+}
diff --git a/cabal.project b/cabal.project
index 1fdea4fb117b691b5573b1120e9e25183fb385dc..8fce413e7f424eff67030561cecafe14457b9a3b 100644
--- a/cabal.project
+++ b/cabal.project
@@ -13,8 +13,7 @@ packages: cabal-benchmarks/
 
 packages: vendor/cabal-doctest-1.0.8
 
--- Uncomment to allow picking up extra local unpacked deps:
---optional-packages: */
+optional-packages: ./vendored/*/*.cabal
 
 -- Remove after hackage-repo-tool release
 allow-newer: