Add initial support for Sandstorm (packaging)

James Mills 1 year ago
parent 54f946613b
commit cac89f130e
Signed by: prologic
GPG Key ID: AC4C014F1440EBD6

.gitignore vendored

@ -11,6 +11,7 @@ yarnd_linux

@ -0,0 +1,5 @@
# vagrant-spk creates shell scripts, which must end in \n, even on a \r\n system.
*.sh text eol=lf

@ -0,0 +1,8 @@
# This file stores a list of sub-paths of .sandstorm/ that should be ignored by git.
# Vagrant sometimes generates log files:

@ -0,0 +1,110 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# CAUTION: DO NOT MAKE CHANGES TO THIS FILE. The vagrant-spk upgradevm process will overwrite it.
# Guess at a reasonable name for the VM based on the folder vagrant-spk is
# run from. The timestamp is there to avoid conflicts if you have multiple
# folders with the same name.
VM_NAME = File.basename(File.dirname(File.dirname(__FILE__))) + "_sandstorm_#{}"
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
# ugly hack to prevent hashicorp's bitrot. See
# this setting is required for pre-2.0 vagrant, but causes an error as of 2.0.3,
# remove entirely when confident nobody uses vagrant 1.x for anything.
unless Vagrant::DEFAULT_SERVER_URL.frozen?
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Base on a 64-bit Debian box with vboxsf support (ex. contrib-buster64, bullseye64) = "debian/contrib-buster64"
config.vm.post_up_message = "Your virtual server is running at:"
if Vagrant.has_plugin?("vagrant-vbguest") then
# vagrant-vbguest is a Vagrant plugin that upgrades
# the version of VirtualBox Guest Additions within each
# guest. If you have the vagrant-vbguest plugin, then it
# needs to know how to compile kernel modules, etc., and so
# we give it this hint about operating system type.
config.vm.guest = "debian"
# We forward port 6090, the vagrant-spk web port, so that developers can
# visit their Sandstorm app from their browser as
# (aka :forwarded_port, guest: 6090, host: 6090, host_ip: ""
# Use a shell script to "provision" the box. This installs Sandstorm using
# the bundled installer.
config.vm.provision "shell", inline: "sudo bash /opt/app/.sandstorm/", keep_color: true
# Then, do stack-specific and app-specific setup.
config.vm.provision "shell", inline: "sudo bash /opt/app/.sandstorm/", keep_color: true
# Shared folders are configured per-provider since vboxsf can't handle >4096 open files,
# NFS requires privilege escalation every time you bring a VM up,
# and 9p is only available on libvirt.
# Calculate the number of CPUs and the amount of RAM the system has,
# in a platform-dependent way; further logic below.
cpus = nil
total_kB_ram = nil
host = RbConfig::CONFIG['host_os']
if host =~ /darwin/
cpus = `sysctl -n hw.ncpu`.to_i
total_kB_ram = `sysctl -n hw.memsize`.to_i / 1024
elsif host =~ /linux/
cpus = `nproc`.to_i
total_kB_ram = `grep MemTotal /proc/meminfo | awk '{print $2}'`.to_i
elsif host =~ /mingw/
cpus = `powershell -Command "(Get-WmiObject Win32_Processor -Property NumberOfLogicalProcessors | Select-Object -Property NumberOfLogicalProcessors | Measure-Object NumberOfLogicalProcessors -Sum).Sum"`.to_i
total_kB_ram = `powershell -Command "[math]::Round((Get-WmiObject -Class Win32_ComputerSystem).TotalPhysicalMemory)"`.to_i / 1024
# Use the same number of CPUs within Vagrant as the system, with 1
# as a default.
# Use at least 512MB of RAM, and if the system has more than 2GB of
# RAM, use 1/4 of the system RAM. This seems a reasonable compromise
# between having the Vagrant guest operating system not run out of
# RAM entirely (which it basically would if we went much lower than
# 512MB) and also allowing it to use up a healthily large amount of
# RAM so it can run faster on systems that can afford it.
if cpus.nil? or
cpus = 1
if total_kB_ram.nil? or total_kB_ram < 2048000
assign_ram_mb = 512
assign_ram_mb = (total_kB_ram / 1024 / 4)
# Actually apply these CPU/memory values to the providers.
config.vm.provider :virtualbox do |vb, override|
vb.cpus = cpus
vb.memory = assign_ram_mb = VM_NAME
vb.customize ["modifyvm", :id, "--nictype1", "Am79C973"]
# /opt/app and /host-dot-sandstorm are used by vagrant-spk
override.vm.synced_folder "..", "/opt/app"
override.vm.synced_folder ENV["HOME"] + "/.sandstorm", "/host-dot-sandstorm"
# /vagrant is not used by vagrant-spk; we need this line so it gets disabled; if we removed the
# line, vagrant would automatically insert a synced folder in /vagrant, which is not what we want.
override.vm.synced_folder "..", "/vagrant", disabled: true
config.vm.provider :libvirt do |libvirt, override|
libvirt.cpus = cpus
libvirt.memory = assign_ram_mb
libvirt.default_prefix = VM_NAME
# /opt/app and /host-dot-sandstorm are used by vagrant-spk
override.vm.synced_folder "..", "/opt/app", type: "9p", accessmode: "passthrough"
override.vm.synced_folder ENV["HOME"] + "/.sandstorm", "/host-dot-sandstorm", type: "9p", accessmode: "passthrough"
# /vagrant is not used by vagrant-spk; we need this line so it gets disabled; if we removed the
# line, vagrant would automatically insert a synced folder in /vagrant, which is not what we want.
override.vm.synced_folder "..", "/vagrant", type: "9p", accessmode: "passthrough", disabled: true

@ -0,0 +1,22 @@
set -euo pipefail
cd /opt/app
if [ ! -e go.mod ]; then
printf "Error: This directory does not contain a go module;\n"
printf "vagrant-spk's golang stack does not support older GOPATH\n"
printf "based projects. Try running:\n" >&2
printf "\n" >&2
printf " vagrant-spk vm ssh\n" >&2
printf " cd /opt/app\n" >&2
printf " go mod init\n" >&2
exit 1
make deps
make preflight server
mv yarnd app
exit 0

@ -0,0 +1,59 @@
set -euo pipefail
# CAUTION: DO NOT MAKE CHANGES TO THIS FILE. The vagrant-spk upgradevm process will overwrite it.
# App-specific setup should be done in the file.
# Set options for curl. Since we only want to show errors from these curl commands, we also use
# 'cat' to buffer the output; for more information:
CURL_OPTS="--silent --show-error"
echo localhost > /etc/hostname
hostname localhost
# Grub updates don't silent install well
apt-mark hold grub-pc
apt-get update
apt-get upgrade -y
# Install curl that is needed below.
apt-get install -y curl
# The following line copies stderr through stderr to cat without accidentally leaving it in the
# output file. Be careful when changing. See:
curl $CURL_OPTS 2>&1 > /host-dot-sandstorm/caches/ | cat
if [[ ! -f /host-dot-sandstorm/caches/$SANDSTORM_PACKAGE ]] ; then
echo -n "Downloading Sandstorm version ${SANDSTORM_CURRENT_VERSION}..."
curl $CURL_OPTS --output "/host-dot-sandstorm/caches/$SANDSTORM_PACKAGE.partial" "$SANDSTORM_PACKAGE" 2>&1 | cat
mv "/host-dot-sandstorm/caches/$SANDSTORM_PACKAGE.partial" "/host-dot-sandstorm/caches/$SANDSTORM_PACKAGE"
echo "...done."
if [ ! -e /opt/sandstorm/latest/sandstorm ] ; then
echo -n "Installing Sandstorm version ${SANDSTORM_CURRENT_VERSION}..."
bash /host-dot-sandstorm/caches/ -d -e -p 6090 "/host-dot-sandstorm/caches/$SANDSTORM_PACKAGE" >/dev/null
echo "...done."
modprobe ip_tables
# Make the vagrant user part of the sandstorm group so that commands like
# `spk dev` work.
usermod -a -G 'sandstorm' 'vagrant'
# Bind to all addresses, so the vagrant port-forward works.
sudo sed --in-place='' \
--expression='s/^BIND_IP=.*/BIND_IP=' \
# Force vagrant-spk to use the strict CSP, see sandstorm#3424 for details.
echo 'ALLOW_LEGACY_RELAXED_CSP=false' >> /opt/sandstorm/sandstorm.conf
sudo service sandstorm restart
# Enable apt-cacher-ng proxy to make things faster if one appears to be running on the gateway IP
GATEWAY_IP=$(ip route | grep ^default | cut -d ' ' -f 3)
if nc -z "$GATEWAY_IP" 3142 ; then
echo "Acquire::http::Proxy \"http://$GATEWAY_IP:3142\";" > /etc/apt/apt.conf.d/80httpproxy
# Configure apt to retry fetching things that fail to download.
echo "APT::Acquire::Retries \"10\";" > /etc/apt/apt.conf.d/80sandstorm-retry

@ -0,0 +1 @@
exec /opt/app/app

@ -0,0 +1,34 @@
# This file is automatically updated and rewritten in sorted order every time
# the app runs in dev mode. You may manually add or remove files, but don't
# expect comments or ordering to be retained.

@ -0,0 +1,252 @@
using Spk = import "/sandstorm/package.capnp";
# This imports:
# $SANDSTORM_HOME/latest/usr/include/sandstorm/package.capnp
# Check out that file to see the full, documented package definition format.
const pkgdef :Spk.PackageDefinition = (
# The package definition. Note that the spk tool looks specifically for the
# "pkgdef" constant.
id = "2wt7y0gya6zdj852v7yc5jnqs7y49z8yqy140tc8t72yqydt0gxh",
# Your app ID is actually its public key. The private key was placed in
# your keyring. All updates must be signed with the same key.
manifest = (
# This manifest is included in your app package to tell Sandstorm
# about your app.
appTitle = (defaultText = ""),
appVersion = 0, # Increment this for every release.
appMarketingVersion = (defaultText = "0.9.0"),
# Human-readable representation of appVersion. Should match the way you
# identify versions of your app in documentation and marketing.
actions = [
# Define your "new document" handlers here.
( nounPhrase = (defaultText = "pod"),
command = .myCommand
# The command to run when starting for the first time. (".myCommand"
# is just a constant defined at the bottom of the file.)
continueCommand = .myCommand,
# This is the command called to start your app back up after it has been
# shut down for inactivity. Here we're using the same command as for
# starting a new instance, but you could use different commands for each
# case.
metadata = (
# Data which is not needed specifically to execute the app, but is useful
# for purposes like marketing and display. These fields are documented at
# and (in deeper detail) in the sandstorm source code, in the Metadata section of
icons = (
# Various icons to represent the app in various contexts.
appGrid = (svg = embed "../assets/logo.svg"),
grain = (svg = embed "../assets/logo.svg"),
market = (svg = embed "../assets/logo.svg"),
marketBig = (svg = embed "../assets/logo.svg"),
website = "",
# This should be the app's main website url.
codeUrl = "",
# URL of the app's source code repository, e.g. a GitHub URL.
# Required if you specify a license requiring redistributing code, but optional otherwise.
license = (none = void),
# The license this package is distributed under. See
categories = [],
# A list of categories/genres to which this app belongs, sorted with best fit first.
# See the list of categories at
author = (
# Fields relating to the author of this app.
contactEmail = "",
# Email address to contact for any issues with this app. This includes end-user support
# requests as well as app store administrator requests, so it is very important that this be a
# valid address with someone paying attention to it.
#pgpSignature = embed "path/to/pgp-signature",
# PGP signature attesting responsibility for the app ID. This is a binary-format detached
# signature of the following ASCII message (not including the quotes, no newlines, and
# replacing <app-id> with the standard base-32 text format of the app's ID):
# "I am the author of the app with the following ID: <app-id>"
# You can create a signature file using `gpg` like so:
# echo -n "I am the author of the app with the following ID: <app-id>" | gpg --sign > pgp-signature
# Further details including how to set up GPG and how to use can be found
# at
upstreamAuthor = " Team",
# Name of the original primary author of this app, if it is different from the person who
# produced the Sandstorm package. Setting this implies that the author connected to the PGP
# signature only "packaged" the app for Sandstorm, rather than developing the app.
# Remove this line if you consider yourself as the author of the app.
#pgpKeyring = embed "path/to/pgp-keyring",
# A keyring in GPG keyring format containing all public keys needed to verify PGP signatures in
# this manifest (as of this writing, there is only one: `author.pgpSignature`).
# To generate a keyring containing just your public key, do:
# gpg --export <key-id> > keyring
# Where `<key-id>` is a PGP key ID or email address associated with the key.
#description = (defaultText = embed "path/to/"),
# The app's description in Github-flavored Markdown format, to be displayed e.g.
# in an app store. Note that the Markdown is not permitted to contain HTML nor image tags (but
# you can include a list of screenshots separately).
shortDescription = (defaultText = "better social media"),
# A very short (one-to-three words) description of what the app does. For example,
# "Document editor", or "Notetaking", or "Email client". This will be displayed under the app
# title in the grid view in the app market.
screenshots = [
# Screenshots to use for marketing purposes. Examples below.
# Sizes are given in device-independent pixels, so if you took these
# screenshots on a Retina-style high DPI screen, divide each dimension by two.
#(width = 746, height = 795, jpeg = embed "path/to/screenshot-1.jpeg"),
#(width = 640, height = 480, png = embed "path/to/screenshot-2.png"),
changeLog = (defaultText = embed "../"),
# Documents the history of changes in Github-flavored markdown format (with the same restrictions
# as govern `description`). We recommend formatting this with an H1 heading for each version
# followed by a bullet list of changes.
sourceMap = (
# Here we defined where to look for files to copy into your package. The
# `spk dev` command actually figures out what files your app needs
# automatically by running it on a FUSE filesystem. So, the mappings
# here are only to tell it where to find files that the app wants.
searchPath = [
( sourcePath = "." ), # Search this directory first.
( sourcePath = "/", # Then search the system root directory.
hidePaths = [ "home", "proc", "sys",
"etc/passwd", "etc/hosts", "etc/host.conf",
"etc/nsswitch.conf", "etc/resolv.conf" ]
# You probably don't want the app pulling files from these places,
# so we hide them. Note that /dev, /var, and /tmp are implicitly
# hidden because Sandstorm itself provides them.
fileList = "sandstorm-files.list",
# `spk dev` will write a list of all the files your app uses to this file.
# You should review it later, before shipping your app.
alwaysInclude = [],
# Fill this list with more names of files or directories that should be
# included in your package, even if not listed in sandstorm-files.list.
# Use this to force-include stuff that you know you need but which may
# not have been detected as a dependency during `spk dev`. If you list
# a directory here, its entire contents will be included recursively.
#bridgeConfig = (
# # Used for integrating permissions and roles into the Sandstorm shell
# # and for sandstorm-http-bridge to pass to your app.
# # Uncomment this block and adjust the permissions and roles to make
# # sense for your app.
# # For more information, see high-level documentation at
# #
# # and advanced details in the "BridgeConfig" section of
# #
# viewInfo = (
# # For details on the viewInfo field, consult "ViewInfo" in
# #
# permissions = [
# # Permissions which a user may or may not possess. A user's current
# # permissions are passed to the app as a comma-separated list of `name`
# # fields in the X-Sandstorm-Permissions header with each request.
# #
# # IMPORTANT: only ever append to this list! Reordering or removing fields
# # will change behavior and permissions for existing grains! To deprecate a
# # permission, or for more information, see "PermissionDef" in
# #
# (
# name = "editor",
# # Name of the permission, used as an identifier for the permission in cases where string
# # names are preferred. Used in sandstorm-http-bridge's X-Sandstorm-Permissions HTTP header.
# title = (defaultText = "editor"),
# # Display name of the permission, e.g. to display in a checklist of permissions
# # that may be assigned when sharing.
# description = (defaultText = "grants ability to modify data"),
# # Prose describing what this role means, suitable for a tool tip or similar help text.
# ),
# ],
# roles = [
# # Roles are logical collections of permissions. For instance, your app may have
# # a "viewer" role and an "editor" role
# (
# title = (defaultText = "editor"),
# # Name of the role. Shown in the Sandstorm UI to indicate which users have which roles.
# permissions = [true],
# # An array indicating which permissions this role carries.
# # It should be the same length as the permissions array in
# # viewInfo, and the order of the lists must match.
# verbPhrase = (defaultText = "can make changes to the document"),
# # Brief explanatory text to show in the sharing UI indicating
# # what a user assigned this role will be able to do with the grain.
# description = (defaultText = "editors may view all site data and change settings."),
# # Prose describing what this role means, suitable for a tool tip or similar help text.
# ),
# (
# title = (defaultText = "viewer"),
# permissions = [false],
# verbPhrase = (defaultText = "can view the document"),
# description = (defaultText = "viewers may view what other users have written."),
# ),
# ],
# ),
# #apiPath = "/api",
# # Apps can export an API to the world. The API is to be used primarily by Javascript
# # code and native apps, so it can't serve out regular HTML to browsers. If a request
# # comes in to your app's API, sandstorm-http-bridge will prefix the request's path with
# # this string, if specified.
const myCommand :Spk.Manifest.Command = (
# Here we define the command used to start up your server.
argv = ["/sandstorm-http-bridge", "8000", "--", "/bin/bash", "/opt/app/.sandstorm/"],
environ = [
# Note that this defines the *entire* environment seen by your app.
(key = "PATH", value = "/usr/local/bin:/usr/bin:/bin"),
(key = "SANDSTORM", value = "1"),
(key = "DEBUG", value = "true"),
(key = "DATA", value = "/var/data"),
(key = "STORE", value = "bitcask:///var/data/yarn.db"),
(key = "OPEN_REGISTRATIONS", value = "true"),
(key = "OPEN_PROFILES", value = "true"),
# Export SANDSTORM=1 into the environment, so that apps running within Sandstorm
# can detect if $SANDSTORM="1" at runtime, switching UI and/or backend to use
# the app's Sandstorm-specific integration code.

@ -0,0 +1,22 @@
# When you change this file, you must take manual action. Read this doc:
# -
set -euo pipefail
# The version of golang in the debian repositories tends to be incredibly
# out of date; let's get ourselves a newer version from upstream:
curl -L${version}.${os}-${arch}.tar.gz -o go.tar.gz
tar -C /usr/local -xzf go.tar.gz
rm go.tar.gz
echo 'export PATH=/usr/local/go/bin:$PATH' > /etc/profile.d/
# Needed for fetching go libraries:
apt-get install -y git
exit 0

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="" xmlns:xlink="" x="0px" y="0px"
viewBox="0 0 487.002 487.002" style="enable-background:new 0 0 487.002 487.002;" xml:space="preserve">
<path d="M416.854,74.149C371.618,28.914,311.475,4.001,247.502,4.001S123.386,28.914,78.15,74.149
c45.235-45.236,70.148-105.379,70.148-169.352S462.089,119.385,416.854,74.149z M421.065,385.926L228.892,467.23
c-13.553-1.105-26.86-3.414-39.797-6.875l254.722-107.767C437.296,364.284,429.701,375.442,421.065,385.926z M393.928,413.695
c-35.626,30.746-79.424,49.25-126.214,53.398L393.928,413.695z M453.855,332.19c-0.429,0.097-0.856,0.226-1.276,0.404
C470.684,269.43,469.558,277.815,467.98,286.078z M54.01,357.506l410.063-173.488c1.945,7.125,3.537,14.363,4.772,21.694
L66.255,376.039C61.852,370.045,57.769,363.861,54.01,357.506z M37.922,324.313l212.463-89.888c0.024-0.01,0.047-0.02,0.071-0.03
C33.271,175.414,36.214,166.742,39.681,158.286z M58.943,121.549l124.788,124.788l-24.445,10.342L46.295,143.688
C50.073,136.091,54.296,128.703,58.943,121.549z M105.029,279.634l-24.445,10.342l-57.322-57.322
c0.498-10.531,1.73-20.927,3.651-31.136L105.029,279.634z M23.243,253.849l42.434,42.434l-32.67,13.822
C27.419,292.029,24.114,273.161,23.243,253.849z M94.157,79.549c8.163-7.647,16.8-14.618,25.845-20.886v46.731L94.157,79.549z
M135.002,49.131c8.078-4.694,16.425-8.865,25-12.493v108.757l-25-25V49.131z M175.002,30.924c8.171-2.779,16.515-5.084,25-6.903
v161.373l-25-25V30.924z M215.002,21.33c8.233-1.187,16.577-1.917,25-2.191V222.53l-2.013,0.851l-22.987-22.987V21.33z
M400.002,154.838l-25,10.577V58.664c8.734,6.052,17.087,12.761,25,20.1V154.838z M360.002,171.761l-25,10.577v-145.7
c8.575,3.628,16.922,7.8,25,12.493V171.761z M320.002,188.684l-25,10.577V24.022c8.485,1.819,16.829,4.124,25,6.903V188.684z
M280.002,205.607l-25,10.577V19.138c8.423,0.275,16.767,1.005,25,2.191V205.607z M444.661,135.944l-29.659,12.548V94.029
C426.571,106.961,436.491,121.018,444.661,135.944z M83.55,90.156l139.533,139.533l-24.445,10.342L67.668,109.06
C72.582,102.515,77.882,96.206,83.55,90.156z M75.894,388.248l395.013-167.121c0.726,7.388,1.094,14.853,1.094,22.374


Width:  |  Height:  |  Size: 3.5 KiB