## Sandstorm Dev Notes -- Part 1 Published 2017-11-17 I like [Sandstorm](https://sandstorm.io) so much that I'm finally developing an app for it. It'll use [PostGraphQL](https://github.com/postgraphql/postgraphql) to move all of the business logic into PostgreSQL, and React, Redux, and Apollo to handle the UI and data reading/manipulation. I'll be documenting the weird issues I've run into when setting this up, since there aren't a ton of docs on this particular combo of services. ## PostgreSQL ### `initdb` Due to how grains have random UID/GID assigned to them for security purposes, and because `/etc/passwd` and `/etc/group` are not available when running `launcher.sh`, `initdb` will fail because it wants to look up the current UID in `/etc/passwd` for security reasons. You can get around this by using [`nss_wrapper`](https://cwrap.org/nss_wrapper.html): ``` export PGDATA=/var/lib/postgres echo "postgres:x:$(id -u):$(id -g):PostgreSQL user:/var/lib/postgres:/bin/sh" > /var/passwd echo "postgres:x:$(id -g):" > /var/group if [ ! -d $PGDATA ]; then LD_PRELOAD=/usr/lib/libnss_wrapper.so NSS_WRAPPER_PASSWD=/var/passwd NSS_WRAPPER_GROUP=/var/group /usr/lib/postgresql/10/bin/initdb fi ``` ### `localhost` Since you don't have `/etc`. you also don't have `/etc/hosts`, which is where the hostname `localhost` is defined. Use `127.0.0.1` everywhere (your app, PostgreSQL config) instead. ## NodeJS ### `HOME` Some Node modules want your `HOME` directory: ``` /usr/lib/node_modules/npm/node_modules/update-notifier/node_modules/xdg-basedir/index.js:5 const home = os.homedir(); ^ Error: ENOENT: no such file or directory, uv_os_homedir ``` `export HOME=/var` at the top of `launcher.sh` will fix it. ## Apollo Client, and all XHR for that matter You'll want to [send cookies from the grain frame](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials) along with your request, otherwise XHR won't work. In an Apollo client for GraphQL requests, that looks like this (bonus `Authentication` header setting for PostGraphQL): ``` js import { ApolloClient } from 'apollo-client'; import { createHttpLink } from 'apollo-link-http'; import { InMemoryCache } from 'apollo-cache-inmemory'; import { setContext } from 'apollo-link-context'; const httpLink = createHttpLink({ uri: '/graphql' }); const authLink = setContext((_, { headers }) => { const { jwtToken } = place.where.jwt.token.stored; const newHeaders = {}; if (jwtToken) { newHeaders.authorization = `Bearer ${jwtToken}`; } return { headers: { ...headers, ...newHeaders, }, credentials: 'include', // gets XHR working with Sandstorm }; }); export default new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), }); ```