From 978987de62eef8c4a375ada80a51cdb21e4127cb Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 3 Aug 2015 15:19:32 -0500 Subject: [PATCH] Initial commit. --- .gitignore | 1 + .sandstorm/Vagrantfile | 83 +++++++++++++++++++++++++++++++ .sandstorm/build.sh | 23 +++++++++ .sandstorm/global-setup.sh | 30 +++++++++++ .sandstorm/launcher.sh | 33 ++++++++++++ .sandstorm/sandstorm-pkgdef.capnp | 81 ++++++++++++++++++++++++++++++ .sandstorm/setup.sh | 28 +++++++++++ .sandstorm/stack | 1 + 8 files changed, 280 insertions(+) create mode 100644 .gitignore create mode 100644 .sandstorm/Vagrantfile create mode 100644 .sandstorm/build.sh create mode 100644 .sandstorm/global-setup.sh create mode 100644 .sandstorm/launcher.sh create mode 100644 .sandstorm/sandstorm-pkgdef.capnp create mode 100644 .sandstorm/setup.sh create mode 100644 .sandstorm/stack diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..8000dd9db --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vagrant diff --git a/.sandstorm/Vagrantfile b/.sandstorm/Vagrantfile new file mode 100644 index 000000000..59daa0e1c --- /dev/null +++ b/.sandstorm/Vagrantfile @@ -0,0 +1,83 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # We base ourselves off Debian Jessie + config.vm.box = "debian/jessie64" + + 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" + end + + # We forward port 6080, the Sandstorm web port, so that developers can + # visit their sandstorm app from their browser as local.sandstorm.io:6080 + # (aka 127.0.0.1:6080). + config.vm.network :forwarded_port, guest: 6080, host: 6080 + + # 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/global-setup.sh" + # Then, do stack-specific and app-specific setup. + config.vm.provision "shell", inline: "sudo bash /opt/app/.sandstorm/setup.sh" + + # 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 + end + # 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? + cpus = 1 + end + if total_kB_ram.nil? or total_kB_ram < 2048000 + assign_ram_mb = 1024 + else + assign_ram_mb = (total_kB_ram / 1024 / 4) + end + # Actually apply these CPU/memory values to the providers. + config.vm.provider :virtualbox do |vb, override| + vb.cpus = cpus + vb.memory = assign_ram_mb + + override.vm.synced_folder "..", "/opt/app" + override.vm.synced_folder ENV["HOME"] + "/.sandstorm", "/host-dot-sandstorm" + override.vm.synced_folder "..", "/vagrant" + end + config.vm.provider :libvirt do |libvirt, override| + libvirt.cpus = cpus + libvirt.memory = assign_ram_mb + libvirt.random_hostname = true + + override.vm.synced_folder "..", "/opt/app", type: "9p", accessmode: "passthrough" + override.vm.synced_folder ENV["HOME"] + "/.sandstorm", "/host-dot-sandstorm", type: "9p", accessmode: "passthrough" + override.vm.synced_folder "..", "/vagrant", type: "9p", accessmode: "passthrough" + end +end diff --git a/.sandstorm/build.sh b/.sandstorm/build.sh new file mode 100644 index 000000000..2f57a5aae --- /dev/null +++ b/.sandstorm/build.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -euo pipefail +# This script is run in the VM each time you run `vagrant-spk dev`. This is +# the ideal place to invoke anything which is normally part of your app's build +# process - transforming the code in your repository into the collection of files +# which can actually run the service in production +# +# Some examples: +# +# * For a C/C++ application, calling +# ./configure && make && make install +# * For a Python application, creating a virtualenv and installing +# app-specific package dependencies: +# virtualenv /opt/app/env +# /opt/app/env/bin/pip install -r /opt/app/requirements.txt +# * Building static assets from .less or .sass, or bundle and minify JS +# * Collecting various build artifacts or assets into a deployment-ready +# directory structure + +# By default, this script does nothing. You'll have to modify it as +# appropriate for your application. +cabal update +cabal install hledger-web-0.26 \ No newline at end of file diff --git a/.sandstorm/global-setup.sh b/.sandstorm/global-setup.sh new file mode 100644 index 000000000..303c9d22c --- /dev/null +++ b/.sandstorm/global-setup.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -euo pipefail +echo localhost > /etc/hostname +hostname localhost +curl https://install.sandstorm.io/ > /host-dot-sandstorm/caches/install.sh +SANDSTORM_CURRENT_VERSION=$(curl -fs "https://install.sandstorm.io/dev?from=0&type=install") +SANDSTORM_PACKAGE="sandstorm-$SANDSTORM_CURRENT_VERSION.tar.xz" +if [[ ! -f /host-dot-sandstorm/caches/$SANDSTORM_PACKAGE ]] ; then + curl --output "/host-dot-sandstorm/caches/$SANDSTORM_PACKAGE" "https://dl.sandstorm.io/$SANDSTORM_PACKAGE" +fi +bash /host-dot-sandstorm/caches/install.sh -d -e "/host-dot-sandstorm/caches/$SANDSTORM_PACKAGE" +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=0.0.0.0/' \ + /opt/sandstorm/sandstorm.conf +# TODO: update sandstorm installer script to ask about dev accounts, and +# specify a value for this option in the default config? +if ! grep --quiet --no-messages ALLOW_DEV_ACCOUNTS=true /opt/sandstorm/sandstorm.conf ; then + echo "ALLOW_DEV_ACCOUNTS=true" | sudo tee -a /opt/sandstorm/sandstorm.conf + sudo service sandstorm restart +fi +# 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 +fi diff --git a/.sandstorm/launcher.sh b/.sandstorm/launcher.sh new file mode 100644 index 000000000..21210a87f --- /dev/null +++ b/.sandstorm/launcher.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -euo pipefail +# This script is run every time an instance of our app - aka grain - starts up. +# This is the entry point for your application both when a grain is first launched +# and when a grain resumes after being previously shut down. +# +# This script is responsible for launching everything your app needs to run. The +# thing it should do *last* is: +# +# * Start a process in the foreground listening on port 8000 for HTTP requests. +# +# This is how you indicate to the platform that your application is up and +# ready to receive requests. Often, this will be something like nginx serving +# static files and reverse proxying for some other dynamic backend service. +# +# Other things you probably want to do in this script include: +# +# * Building folder structures in /var. /var is the only non-tmpfs folder +# mounted read-write in the sandbox, and when a grain is first launched, it +# will start out empty. It will persist between runs of the same grain, but +# be unique per app instance. That is, two instances of the same app have +# separate instances of /var. +# * Preparing a database and running migrations. As your package changes +# over time and you release updates, you will need to deal with migrating +# data from previous schema versions to new ones, since users should not have +# to think about such things. +# * Launching other daemons your app needs (e.g. mysqld, redis-server, etc.) + +# By default, this script does nothing. You'll have to modify it as +# appropriate for your application. +mkdir -p /var/lib/hledger +touch /var/lib/hledger/ledger.dat +/home/vagrant/.cabal/bin/hledger-web --server -f /var/lib/hledger/ledger.dat --port 8000 \ No newline at end of file diff --git a/.sandstorm/sandstorm-pkgdef.capnp b/.sandstorm/sandstorm-pkgdef.capnp new file mode 100644 index 000000000..dd12e97ef --- /dev/null +++ b/.sandstorm/sandstorm-pkgdef.capnp @@ -0,0 +1,81 @@ +@0xb83da55f33c7fde7; + +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 = "wy71w9g29zevsc8dfcf8c322wgxm97z5fu29y8v9p02p95s6eqj0", + # 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 = "HLedger"), + + appVersion = 0, # Increment this for every release. + + appMarketingVersion = (defaultText = "0.26"), + # 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. + ( title = (defaultText = "New Ledger"), + 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. + ), + + 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. +); + +const myCommand :Spk.Manifest.Command = ( + # Here we define the command used to start up your server. + argv = ["/sandstorm-http-bridge", "8000", "--", "/opt/app/.sandstorm/launcher.sh"], + environ = [ + # Note that this defines the *entire* environment seen by your app. + (key = "PATH", value = "/usr/local/bin:/usr/bin:/bin:/home/vagrant/.cabal/bin") + ] +); diff --git a/.sandstorm/setup.sh b/.sandstorm/setup.sh new file mode 100644 index 000000000..59ff9d34e --- /dev/null +++ b/.sandstorm/setup.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -euo pipefail +# This script is run in the VM once when you first run `vagrant-spk up`. It is +# useful for installing system-global dependencies. It is run exactly once +# over the lifetime of the VM. +# +# This is the ideal place to do things like: +# +# export DEBIAN_FRONTEND=noninteractive +# apt-get install -y nginx nodejs nodejs-legacy python2.7 mysql-server +# +# If the packages you're installing here need some configuration adjustments, +# this is also a good place to do that: +# +# sed --in-place='' \ +# --expression 's/^user www-data/#user www-data/' \ +# --expression 's#^pid /run/nginx.pid#pid /var/run/nginx.pid#' \ +# --expression 's/^\s*error_log.*/error_log stderr;/' \ +# --expression 's/^\s*access_log.*/access_log off;/' \ +# /etc/nginx/nginx.conf + +# By default, this script does nothing. You'll have to modify it as +# appropriate for your application. +apt-get update +apt-get install -y haskell-platform libncurses-dev +mkdir /var/lib/hledger +touch /var/lib/hledger/ledger.dat +chown -R vagrant.vagrant /var/lib/hledger diff --git a/.sandstorm/stack b/.sandstorm/stack new file mode 100644 index 000000000..7c3182e51 --- /dev/null +++ b/.sandstorm/stack @@ -0,0 +1 @@ +diy