Last active
March 14, 2019 21:13
-
-
Save dch/9c651e18f93bd992fa20816956d2fa0a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -e | |
# obvious | |
export APP=$(basename -s .sh $0) | |
# derived paths are OS dependent | |
export ERTS=$(find /usr/local/lib/erlang* -type d -depth 1 -name erts-\* | tail -1) | |
export VERSION=$(cut -swf 2 /usr/local/lib/${APP}/releases/start_erl.data) | |
# config files | |
CONFIGS=/usr/local/etc/${APP} | |
export SYSCONFIG=${CONFIGS}/sys.config | |
export VMARGS=${CONFIGS}/vm.args | |
# if this dir is not writable then the runtime can't start | |
export HOME=/var/run/${APP} | |
# custom parameters | |
# BEAM essentials | |
export LD_LIBRARY_PATH=${ERTS}/lib: | |
export BINDIR=${ERTS}/bin | |
export PATH=${BINDIR}:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | |
export ROOTDIR=/usr/local/lib/${APP} | |
export PROGNAME=${ROOTDIR}/releases/${VERSION}/${APP}.sh | |
export ERL_LIBS=${ROOTDIR}/lib:${ERTS}/../lib | |
export MODE="-mode embedded" | |
# elixir | |
export LANG=en_US.UTF-8 | |
export LC_ALL=en_US.UTF-8 | |
# useful BEAM bits | |
# export ERL_AFLAGS="-kernel shell_history enabled" | |
# no turds on BEAM exit | |
export ERL_CRASH_DUMP=/dev/null | |
export ERL_CRASH_DUMP_BYTES=0 | |
export ERL_CRASH_DUMP_SECONDS=0 | |
# debug beam startup | |
# export VERBOSE="-init_debug " | |
# ensure epmd is managed by OS daemons and not tied to this app | |
# export EPMD="-start_epmd false" | |
# keep user sticky fingers out of the console | |
# see http://erlang.org/doc/man/run_erl.html | |
# export RUN_ERL_DISABLE_FLOWCNTRL=1 | |
# export DOTERL="-boot no_dot_erlang" | |
cd /usr/local/lib/${APP} | |
${BINDIR}/erlexec \ | |
${VERBOSE} \ | |
${DOTERL} \ | |
${EPMD} \ | |
${MODE} \ | |
-boot ${ROOTDIR}/releases/${VERSION}/${APP} \ | |
-boot_var ERTS_LIB_DIR ${ERTS}/../lib \ | |
-env ERL_LIBS ./rel/${APP}/lib \ | |
-pa ${ROOTDIR}/lib/${APP}-${VERSION}/consolidated \ | |
-pz ${ROOTDIR}/lib/${APP}-${VERSION}/ebin \ | |
-args_file ${VMARGS} \ | |
-config ${SYSCONFIG} \ | |
-user Elixir.IEx.CLI \ | |
-extra \ | |
--no-halt \ | |
+iex -- console |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -ex | |
# elixir puts its _build dir in the root of this repo, alongside build.sh | |
cd $(dirname $0) | |
ROOT=$(pwd -P) | |
APP=$(basename $ROOT) | |
BUILD=${ROOT}/_build | |
cd - | |
# borrow rebar from packages | |
test -x ${HOME}/.mix/rebar || mix local.rebar --force rebar /usr/local/bin/rebar | |
test -x ${HOME}/.mix/rebar3 || mix local.rebar --force rebar3 /usr/local/bin/rebar3 | |
# ensure we pick up OTP21 by default | |
export PATH=/usr/local/lib/erlang21/bin:$PATH | |
# UTF8 while we build | |
export LANG=en_US.UTF-8 | |
export LC_ALL=${LANG} | |
export MIX_ENV=prod | |
# clean up any existing release tarballs | |
rm -rf $(find ${ROOT}/rel ${BUILD} -name *z) 2>/dev/null | |
# clean up existing dependencies and build | |
rm -rf ${ROOT}/deps | |
# build stuff | |
cp config/prod.secret.exs.example config/prod.secret.exs | |
mix deps.get --only prod | |
mix release --env=prod | |
RELEASE=$(find ${ROOT} -name ${APP}*tar.gz) 2>/dev/null | |
test -e "${RELEASE}" || exit 1 | |
# use a random temporary dir for everything else | |
BASE=$(mktemp -d /tmp/${APP}.XXXXXX) | |
STAGING=${BASE}/staging | |
DEST=${STAGING}/usr/local/lib/${APP} | |
PKG=${BASE}/package | |
MANIFEST=${PKG}/manifest.ucl | |
mkdir -p -m0750 ${PKG} ${DEST} \ | |
${STAGING}/usr/local/etc/rc.d \ | |
${STAGING}/usr/local/bin | |
# exclude non-root users during tar etc | |
umask 027 | |
# get template manifest and other static files | |
cp -vp ${ROOT}/rc.d ${STAGING}/usr/local/etc/rc.d/${APP} | |
cp -vp ${ROOT}/app.sh ${STAGING}/usr/local/bin/${APP} | |
cp -vp ${ROOT}/manifest.ucl ${MANIFEST} | |
# replace APP with actual app name in rc.d script | |
sed -E -i '' -e "s/APP/${APP}/g" ${STAGING}/usr/local/etc/rc.d/${APP} | |
# unpack the mix release itself excluding files with tokens | |
# these files should be distributed out of band via ops tools | |
tar xzf ${RELEASE} \ | |
-C ${DEST} \ | |
--exclude sys.config \ | |
--exclude vm.args | |
# prepare FreeBSD package manifest | |
## grab the version number from mix | |
DATE=$(date -u +%Y%m%d-%H%M) | |
# get a git tag or nearest sha to use as a suffix to app version | |
GITREF=$(git describe --dirty --abbrev=7 --tags --always --first-parent 2>/dev/null || true) | |
## inject all that into the manifest | |
uclcmd set --file ${MANIFEST} --type string version ${DATE}-${GITREF} | |
# include each file, its hash, and any permissions: | |
# expected result: | |
# /usr/lib/app/bin/app: {sum: 1$abc123, uname: root, gname: www, perm: 0440 } | |
SHA_LIST=$(find ${STAGING} -type f -exec sha256 -r {} + \ | |
| awk '{print " " $2 ": {uname: root, gname: www, sum: 1$" $1"}"}') | |
# include softlinks: | |
# expected result looks like: | |
# /usr/local/lib/symlink: - | |
LINKS_LIST=$(find ${STAGING} -type l \ | |
| awk '{print " " $1 ": -"}') | |
# include app-specific directories and permissions: | |
# make sure we exclude things like /usr /usr/local/ /etc/ that are | |
# already in place as we don't want to change their permissions | |
# expected result looks like: | |
# /usr/local/lib/app: {uname: root, gname: www, perm: 0550}` | |
DIR_LIST=$(find ${STAGING} -type d -mindepth 3 -path \*/${APP}/\* \ | |
| awk '{print " " $1 ": {uname: root, gname: www, perm: 0750}"}') | |
# make runtime directories | |
mkdir -m0770 -p \ | |
${STAGING}/usr/local/etc/${APP} \ | |
${STAGING}/var/db/${APP} \ | |
${STAGING}/var/log/${APP} \ | |
${STAGING}/var/run/${APP} | |
# strip off _build/state prefix and append this UCL snippet to manifest | |
cat <<UCL | sed -E -e s:${STAGING}:: >> ${MANIFEST} | |
files: { | |
$SHA_LIST | |
$LINKS_LIST | |
} | |
directories: { | |
$DIR_LIST | |
/usr/local/etc/${APP}: {uname: root, gname: www, perm: 0770} | |
/var/log/${APP}: {uname: root, gname: www, perm: 0770} | |
/var/run/${APP}: {uname: root, gname: www, perm: 0770} | |
/var/db/${APP}: {uname: root, gname: www, perm: 0770} | |
} | |
UCL | |
## bubblewrap the package and manifest | |
if test "$(uname -s)" == "FreeBSD"; then | |
pkg create --verbose \ | |
--root-dir ${STAGING} \ | |
--manifest ${MANIFEST} \ | |
--out-dir ${BUILD} | |
cp ${MANIFEST} ${BUILD}/ | |
cat << EOF | |
final manifest: $(find ${BUILD} -name manifest.ucl) | |
package complete: $(find ${BUILD} -name *.txz) | |
to install: | |
sudo -s | |
service ${APP} stop | |
pkg install $(find ${BUILD} -name ${APP}\*.txz) | |
service ${APP} start | |
EOF | |
fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: app | |
origin: skunkwerks/app | |
comment: "The first draft of anything is shit." | |
arch: freebsd:12:x86:64 | |
www: https://github.com/skunkwerks/app | |
maintainer: [email protected] | |
prefix: /usr/local | |
licenselogic: single | |
licenses: [MIT] | |
categories: [skunkwerks] | |
deps: {erlang-runtime21: {origin: lang/erlang-runtime21, version: "21"}} | |
flatsize: 0 | |
desc: <<EOD | |
There is nothing to writing. All you do is sit down at a typewriter and bleed. | |
EOD | |
message: <<EOM | |
The best people possess a feeling for beauty, the courage to take risks, the | |
discipline to tell the truth, the capacity for sacrifice. Ironically, their | |
virtues make them vulnerable; they are often wounded, sometimes destroyed. | |
Ensure that you have the following config files in place: | |
- /etc/rc.conf.d/app | |
- /usr/local/etc/app/vm.args | |
- /usr/local/etc/app/sys.config | |
EOM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# | |
# PROVIDE: APP | |
# REQUIRE: networking epmd | |
# AFTER: epmd | |
# KEYWORD: | |
. /etc/rc.subr | |
name="APP" | |
rcvar="${name}_enable" | |
install_dir="/usr/local/lib/${name}" | |
version=$(cut -wf 2 ${install_dir}/releases/start_erl.data) | |
extra_commands="status" | |
start_cmd="${name}_start" | |
stop_cmd="${name}_stop" | |
status_cmd="${name}_status" | |
load_rc_config $name | |
: ${APP_enable:="no"} | |
: ${APP_verbose:=""} | |
: ${APP_user:="www"} | |
: ${APP_command=/usr/local/bin/${name}} | |
APP_run() | |
{ | |
umask 027 | |
/usr/bin/env \ | |
ERL_ZFLAGS="-detached" \ | |
su -m "${APP_user}" -c "${APP_command}" | |
} | |
# On each run, we ensure we are starting from a clean slate. | |
# At shutdown we kill any stray processes just in case. | |
# Logs are stored using syslog but there are some minimal | |
# startup and heart logs from the runtime that are worth | |
# keeping in case of debugging BEAM crashes. | |
APP_start() | |
{ | |
rm -rf /var/run/APP/.erlang.cookie | |
APP_stop | |
APP_run | |
} | |
APP_stop() | |
{ | |
# kill only the process listed in the pidfile and only if the user matches | |
pkill -TERM -U ${APP_user} -f beam.smp | |
sleep 3 | |
pkill -KILL -U ${APP_user} -f beam.smp | |
} | |
APP_status() | |
{ | |
pid_check=$(pgrep -U ${APP_user} -f beam.smp) | |
test "$pid_check" && echo "${name} is running." | |
} | |
load_rc_config $name | |
run_rc_command "$1" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment