2021-09-01: I’ve written a follow-up post covering changes introduced in Hasura v2.0.8.
$WORKPLACE is using Hasura for a project. The core server component of Hasura – the “GraphQL Engine” – is distributed only as a Docker container. This works well enough on my Linux machine, but I have a strong aversion to running Docker on non-Linux machines. I find idea that containers can still be considered “lightweight” when they’re running inside a full-fat VM to be a bit laughable. I prefer to run things on “bare metal” in my development environment where I can. And while Hasura don’t distribute first-party native binaries, there’s hypothetically nothing stopping us from building our own; it is, after all, open source (APL 2.0). So let’s do that.
The Engine is written in Haskell, so as a prerequisite, install ghcup. If it’s been added to your PATH correctly, you should be able to run
ghcup list and get a list of available Haskell compiler (GHC) and build/package manager (Cabal) versions.
Check out the GraphQL Engine Git repository:
$ git clone https://github.com/hasura/graphql-engine.git # Make sure we're building a specific release version, not just the master branch.$ git checkout v1.3.3 # The server-side source code is all in the server/ directory. $ cd graphql-engine/server
The Haskell build manager, Cabal, is almost capable of building the project without intervention. The fly in the ointment is that Hasura seems to be quite picky about the GHC version it’s built with, and Cabal isn’t high enough up the dependency food chain to pick which compiler version gets used. So instead, we’ll need to pull desired GHC and Cabal versions out of the freeze file, and install/set those as the defaults with
# Install the GHC version corresponding to the required Haskell language base version. $ grep 'any.base ==' cabal.project.freeze any.base ==18.104.22.168, $ ghcup install ghc base-22.214.171.124 [ Info ] downloading: https://downloads.haskell.org/~ghc/8.10.1/ghc-8.10.1-x86_64-apple-darwin.tar.xz ... [ Info ] GHC installation successful $ ghcup set ghc base-126.96.36.199 [ Info ] GHC 8.10.1 successfully set as default version $ grep 'any.Cabal ==' cabal.project.freeze constraints: any.Cabal ==188.8.131.52, $ ghcup install cabal 184.108.40.206 [ Info ] downloading: https://downloads.haskell.org/~cabal/cabal-install-220.127.116.11/cabal-install-18.104.22.168-x86_64-apple-darwin17.7.0.tar.xz ... [ Info ] Cabal installation successful $ ghcup set cabal 22.214.171.124 [ Info ] Cabal 126.96.36.199 successfully set as default version
Then you can kick Cabal into action:
$ cabal v2-update (git junk happens) Downloading the latest package list from hackage.haskell.org To revert to previous state run: cabal v2-update 'hackage.haskell.org,...' $ cabal v2-build (git junk happens) Resolving dependencies... Build profile: -w ghc-8.10.1 -O1 In order, the following will be built (use -v for more details): (looong build process happens) Building executable 'graphql-engine' for graphql-engine-1.0.0.. Linking /path/to/graphql-engine/server/dist-newstyle/build/x86_64-osx/ghc-8.10.1/graphql-engine-1.0.0/x/graphql-engine/opt/build/graphql-engine/graphql-engine ...
And that’s it. The long path given by the last line (“Linking…”) is the final executable. It’ll be about 64MB. You can run it as-is and it’ll complain about missing arguments. The documented configuration arguments and environment variables are really just passed through to the binary running in the container, so they’ll work just fine with the binary running out of the container, too. For example, to connect to the local database
testdb as the user
testuser, and enable the console:
/path/to/graphql-engine \ --database-url postgres://testuser@localhost/testdb \ serve \ --enable-console
Then point a browser at http://localhost:8080/console.
Note that the
graphql-engine executable is dynamically linked against a number of other libraries:
$ otool -L /path/to/graphql-engine /path/to/graphql-engine: /usr/local/opt/postgresql/lib/libpq.5.dylib (compatibility version 5.0.0, current version 5.13.0) /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11) /usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1) /usr/lib/libcharset.1.dylib (compatibility version 2.0.0, current version 2.0.0)
Not very portable. To physically relocate these libraries and modify the linking of the
graphql-engine executable for easier distribution, you can either do this yourself with
install_name_tool, or use something like locallink to do it for you.