Initial commit

This commit is contained in:
Akis Kesoglou 2018-06-05 16:07:12 +03:00
parent 2dde9c56c4
commit 6e5a2e36e2
17 changed files with 838 additions and 0 deletions

5
.gitignore vendored
View File

@ -0,0 +1,5 @@
*.srl
.DS_Store
.project
.vagrant/
src/

57
README.md Normal file
View File

@ -0,0 +1,57 @@
## Host requirements
- Docker >= 18.05.0
- Docker Compose >= 1.11
- OpenSSL >= 1.0.0
- Python >= 2.7 or >=3.4
## Installation
### Debian/Ubuntu
Make sure you have the software listed above installed.
In a terminal, change into the `open-balena` directory and create a new
deployment:
$ ./scripts/start-project
This will create a new directory, `demo`, and generate appropriate SSL
certificates and configuration for the platform. You can configure the
deployment name by passing it as the first argument to the `start-project`
command. If you wish to run the platform under a specific domain name,
you can specify it as the second argument. The default is `openbalena.local`.
For example:
$ ./scripts/start-project mydeployment my.domain.com
You can create as many deployments as needed and switch between them using:
$ ./scripts/select-project mydeployment
Remove all traces of a project by deleting its folder.
Start the platform with:
$ ./scripts/run-fig-command up
Stop the platform with:
$ ./scripts/run-fig-command stop
### macOS & Windows
On macOS and Windows you need Vagrant. `open-balena` is not being tested with
docker-machine. `open-balena` comes with an appropriate `Vagrantfile` for
setting up the VM, installing dependencies and starting the platform.
- Install Vagrant >= 2.0
- `$ vagrant plugin install vagrant-docker-compose`
- `$ vagrant up`
When provisioning completes and the VM has started, `open-balena` services
should be running inside the VM. You will need to expose these services to
the outside in order for them to be reachable by devices. To do so, you must
setup DNS for the domain name you've deployed the instance as to point to the
VM's IP address.

30
Vagrantfile vendored Normal file
View File

@ -0,0 +1,30 @@
Vagrant.require_version '>= 2.0.0'
[ 'vagrant-vbguest', 'vagrant-docker-compose' ].each do |p|
unless Vagrant.has_plugin?(p)
raise "Please install missing plugin: vagrant plugin install #{p}"
end
end
Vagrant.configure('2') do |config|
config.vm.define 'open-balena-vm'
config.vm.box = 'bento/ubuntu-16.04'
config.vm.box_url = 'https://vagrantcloud.com/bento/boxes/ubuntu-16.04/versions/201803.24.0/providers/virtualbox.box'
config.vm.synced_folder '.', '/vagrant', disabled: true
config.vm.synced_folder '.', '/home/vagrant/open-balena'
config.vm.network 'public_network', bridge: ENV.fetch('OPENBALENA_BRIDGE', true)
config.ssh.forward_agent = true
config.vm.provision :docker
config.vm.provision :docker_compose
# FIXME: remove node
config.vm.provision :shell, inline: 'apt-get install nodejs'
# FIXME: remove `docker login`
config.vm.provision :shell, inline: "docker login --username resindev --password #{ENV.fetch('DOCKERHUB_PASSWORD')}"
config.vm.provision :shell, inline: '/home/vagrant/open-balena/scripts/start-project'
config.vm.provision :shell, inline: '/home/vagrant/open-balena/scripts/run-fig-command up -d', run: 'always'
end

15
compose/common.yml Normal file
View File

@ -0,0 +1,15 @@
version: '2.1'
services:
component:
cap_add:
- SYS_ADMIN
- SYS_RESOURCE
environment:
- CONFD_BACKEND=ENV
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
system:
security_opt:
- seccomp:unconfined

217
compose/services.yml Normal file
View File

@ -0,0 +1,217 @@
version: '2.1'
volumes:
db:
registry:
# FIXME: remove
img:
services:
api:
extends:
file: ./common.yml
service: component
image: resin/resin-api:${OPENBALENA_API_VERSION_TAG:-master}
depends_on:
- db
security_opt:
- seccomp:unconfined
environment:
ADMIN_LIST:
AUTH_RESINOS_REGISTRY_CODE: ${OPENBALENA_RESINOS_REGISTRY_CODE}
BALENA_ROOT_CA: ${OPENBALENA_ROOT_CA}
DB_HOST: db
DB_PASSWORD: docker
DB_PORT: 5432
DB_USER: docker
DEBUG: '${OPENBALENA_DEBUG}'
DEVICE_CONFIG_OPENVPN_CA: yyy
DEVICE_CONFIG_OPENVPN_CONFIG: yyy
DEVICE_CONFIG_SSH_AUTHORIZED_KEYS: yyy
EMAIL_RECIPIENT_OVERRIDE:
HOST: ${OPENBALENA_HOST_NAME}
IMAGE_MAKER_URL: img.${OPENBALENA_HOST_NAME}
JSON_WEB_TOKEN_EXPIRY_MINUTES: 10080
JSON_WEB_TOKEN_SECRET: ${OPENBALENA_JWT_SECRET}
PRODUCTION_MODE: '${OPENBALENA_PRODUCTION_MODE}'
REGISTRY2_HOST: registry.${OPENBALENA_HOST_NAME}
TOKEN_AUTH_CERT_ISSUER: api.${OPENBALENA_HOST_NAME}
TOKEN_AUTH_CERT_KEY: ${OPENBALENA_TOKEN_AUTH_KEY}
TOKEN_AUTH_CERT_KID: ${OPENBALENA_TOKEN_AUTH_KID}
TOKEN_AUTH_CERT_PUB: ${OPENBALENA_TOKEN_AUTH_PUB}
TOKEN_AUTH_JWT_ALGO: 'ES256'
VPN_HOST: vpn.${OPENBALENA_HOST_NAME}
VPN_PORT: 443
VPN_SERVICE_API_KEY: ${OPENBALENA_VPN_SERVICE_API_KEY}
# FIXME: remove all the following
ADMIN_HOST: __unused__
AUTH_FACEBOOK_CLIENT_ID: __unused__
AUTH_FACEBOOK_CLIENT_SECRET: __unused__
AUTH_GITHUB_CLIENT_ID: __unused__
AUTH_GITHUB_CLIENT_SECRET: __unused__
AUTH_GOOGLE_CLIENT_ID: __unused__
AUTH_GOOGLE_CLIENT_SECRET: __unused__
AUTH_TWITTER_CONSUMER_KEY: __unused__
AUTH_TWITTER_CONSUMER_SECRET: __unused__
BUILDER_SERVICE_API_KEY: __unused__1 # must be unique
COOKIE_SESSION_SECRET: __unused__
DB_ANALYTICS_PASSWORD:
DELTA_HOST: __unused__
DELTA_SERVICE_API_KEY: __unused__2 # must be unique
DEVICE_URLS_BASE: __unused__
DIGITIZER_API_KEY: __unused__3 # must be unique
GA_ID: __unused__
GA_SITE: __unused__
GEOIP_LICENCE_KEY: __unused__
GEOIP_USER_ID: __unused__
GIT_HOST: __unused__
GIT_HOSTNAME: __unused__
GIT_PORT: 80
GIT_SERVICE_API_KEY: __unused__4 # must be unique
INTERCOM_APP_ID: __unused__
INTERCOM_SECRET_KEY: __unused__
MAILGUN_API_KEY: __unused__
MAILGUN_DOMAIN: __unused__
MIXPANEL_ACCOUNT_ID: __unused__
MIXPANEL_API_KEY: __unused__
MIXPANEL_API_SECRET: __unused__
MIXPANEL_TOKEN: __unused__
PROXY_SERVICE_API_KEY: __unused__5 # must be unique
PUBNUB_PUBLISH_KEY: __unused__
PUBNUB_SUBSCRIBE_KEY: __unused__
RECAPTCHA_PRIVATE_KEY: __unused__
RECAPTCHA_PUBLIC_KEY: __unused__
RECURLY_PRIVATE_KEY: __unused__
RECURLY_PUBLIC_KEY: __unused__
RECURLY_SUBDOMAIN: __unused__
REDIS_HOST: __unused__
REDIS_PORT: 6379
REGISTRY_HOST: __unused__
SENTRY_DSN:
TOKEN_AUTH_BUILDER_TOKEN: __unused__
TWOFACTOR_ISSUER: __unused__
UI_HOST: __unused__
ZENDESK_DOMAIN: __unused__
ZENDESK_SHARED_SECRET: __unused__
registry:
extends:
file: ./common.yml
service: component
image: resin/open-balena-registry:${OPENBALENA_REGISTRY_VERSION_TAG:-master}
depends_on:
- api
volumes:
- registry:/data
environment:
API_TOKENAUTH_CRT: ${OPENBALENA_TOKEN_AUTH_PUB}
BALENA_ROOT_CA: ${OPENBALENA_ROOT_CA}
COMMON_REGION:
REGISTRY2_HOST: registry.${OPENBALENA_HOST_NAME}
REGISTRY2_S3_BUCKET:
REGISTRY2_S3_KEY:
REGISTRY2_S3_SECRET:
REGISTRY2_STORAGEPATH: /data
TOKENAUTH_ISSUER: api.${OPENBALENA_HOST_NAME}
TOKENAUTH_REALM: https://api.${OPENBALENA_HOST_NAME}/auth/v1/token
# FIXME: remove the following
REGISTRY2_SECRETKEY: __unused__
vpn:
extends:
file: ./common.yml
service: component
image: resin/resin-vpn:${OPENBALENA_VPN_VERSION_TAG:-master}
depends_on:
- api
cap_add:
- NET_ADMIN
environment:
BALENA_ROOT_CA: ${OPENBALENA_ROOT_CA}
BALENA_VPN_PORT: 443
LOGENTRIES_TOKEN:
PRODUCTION_MODE: '${OPENBALENA_PRODUCTION_MODE}'
RESIN_API_HOST: api.${OPENBALENA_HOST_NAME}
RESIN_VPN_GATEWAY: 10.2.0.1
SENTRY_DSN:
VPN_HAPROXY_USEPROXYPROTOCOL: 'true'
VPN_SERVICE_API_KEY: ${OPENBALENA_VPN_SERVICE_API_KEY}
# FIXME: remove all of the following
API_SERVICE_API_KEY: __unused__
PROXY_SERVICE_API_KEY: __unused__5
db:
extends:
file: ./common.yml
service: system
image: resin/open-balena-db:${OPENBALENA_DB_VERSION_TAG:-master}
volumes:
- db:/var/lib/postgresql/data
haproxy:
extends:
file: ./common.yml
service: system
build: ../haproxy
depends_on:
- api
- registry
- vpn
- db
# FIXME: remove
- proxy
- img
ports:
- "80:80"
- "222:222"
- "443:443"
- "5432:5432"
environment:
BALENA_ROOT_CA: ${OPENBALENA_ROOT_CA}
HAPROXY_HOSTNAME: ${OPENBALENA_HOST_NAME}
# FIXME: remove the following
proxy:
extends:
file: ./common.yml
service: component
image: resin/resin-proxy:${OPENBALENA_PROXY_VERSION_TAG:-master}
depends_on:
- api
- vpn
environment:
BALENA_ROOT_CA: ${OPENBALENA_ROOT_CA}
DEBUG: '${OPENBALENA_DEBUG}'
DEVICE_URLS_BASE: devices.${OPENBALENA_HOST_NAME}
IDLE_CONNECTION_TIMEOUT: 50
JSON_WEB_TOKEN_SECRET: ${OPENBALENA_JWT_SECRET}
LOGENTRIES_TOKEN:
PRODUCTION_MODE: '${OPENBALENA_PRODUCTION_MODE}'
PROXY_PROTOCOL_PORTS:
PROXY_SERVICE_API_KEY: __unused__5
RESIN_API_HOST: api.${OPENBALENA_HOST_NAME}
SENTRY_DSN:
img:
extends:
file: ./common.yml
service: component
image: resin/resin-img:${OPENBALENA_IMG_VERSION_TAG:-master}
depends_on:
- api
volumes:
- img:/prepdir
environment:
BALENA_ROOT_CA: ${OPENBALENA_ROOT_CA}
DEVELOPMENT: 1
LKL_MEMORY: 268435456
LOGENTRIES_TOKEN:
NODEPING_KEY: xxx
RESIN_IMG_S3_ACCESS_KEY: abcdef1234
RESIN_IMG_S3_BUCKET: resin-image-maker
RESIN_IMG_S3_ENDPOINT: s3.${OPENBALENA_HOST_NAME}
RESIN_IMG_S3_FORCE_PATH_STYLE: 'true'
RESIN_IMG_S3_SECRET_KEY: 1234567890
RESIN_IMG_STORAGE_DRIVER: passthrough
SENTRY_DSN:

6
haproxy/Dockerfile Normal file
View File

@ -0,0 +1,6 @@
FROM haproxy:1.8-alpine
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
COPY entry.sh /open-balena-entry
CMD /open-balena-entry

9
haproxy/entry.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
CA_B64="$BALENA_ROOT_CA"
CA_FILE=/etc/ssl/private/root.chain.pem
mkdir -p $(dirname "$CA_FILE")
echo "$CA_B64" | base64 -d >"$CA_FILE"
exec haproxy -f /usr/local/etc/haproxy/haproxy.cfg

123
haproxy/haproxy.cfg Normal file
View File

@ -0,0 +1,123 @@
global
tune.ssl.default-dh-param 1024
defaults
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http-in
mode http
option forwardfor
bind *:80
reqadd X-Forwarded-Proto:\ http
acl host_api hdr_dom(host) -i "api.${HAPROXY_HOSTNAME}"
use_backend backend_api if host_api
acl host_registry hdr_dom(host) -i "registry.${HAPROXY_HOSTNAME}"
use_backend backend_registry if host_registry
acl host_vpn hdr_dom(host) -i "vpn.${HAPROXY_HOSTNAME}"
use_backend backend_vpn if host_vpn
# FIXME: remove
acl host_proxy hdr_dom(host) -i "devices.${HAPROXY_HOSTNAME}"
use_backend backend_proxy if host_proxy
# FIXME: remove
acl host_img hdr_dom(host) -i "img.${HAPROXY_HOSTNAME}"
use_backend backend_img if host_img
frontend ssl-in
mode tcp
bind *:443
tcp-request inspect-delay 2s
tcp-request content accept if { req.ssl_hello_type 1 }
acl is_ssl req.ssl_ver 2:3.4
use_backend redirect-to-https-in if is_ssl
use_backend vpn-devices if !is_ssl
backend redirect-to-https-in
mode tcp
balance roundrobin
server localhost 127.0.0.1:444 send-proxy-v2
frontend https-in
mode http
option forwardfor
bind 127.0.0.1:444 ssl crt /etc/ssl/private/root.chain.pem accept-proxy
reqadd X-Forwarded-Proto:\ https
acl host_api hdr_dom(host) -i "api.${HAPROXY_HOSTNAME}"
use_backend backend_api if host_api
acl host_registry hdr_dom(host) -i "registry.${HAPROXY_HOSTNAME}"
use_backend backend_registry if host_registry
# FIXME: remove
acl host_proxy hdr_dom(host) -i "devices.${HAPROXY_HOSTNAME}"
use_backend backend_proxy if host_proxy
# FIXME: remove
acl host_img hdr_dom(host) -i "img.${HAPROXY_HOSTNAME}"
use_backend backend_img if host_img
backend backend_api
mode http
option forwardfor
balance roundrobin
server resin_api_1 api:80 check port 80
backend backend_registry
mode http
option forwardfor
balance roundrobin
server resin_registry_1 registry:80 check port 80
backend backend_vpn
mode http
option forwardfor
balance roundrobin
server resin_vpn_1 vpn:80 check port 80
# FIXME: remove
backend backend_proxy
mode http
option forwardfor
balance roundrobin
server resin_proxy_1 proxy:80 send-proxy check-send-proxy port 80
# FIXME: remove
backend backend_img
mode http
option forwardfor
balance roundrobin
server resin_img_1 img:80 check port 80
# FIXME: remove
frontend devices-ssh-gateway
mode tcp
bind *:222
default_backend devices-ssh-gateway
timeout client 1h
# FIXME: remove
backend devices-ssh-gateway
mode tcp
server resin_proxy_1 proxy:2222 check port 2222
backend vpn-devices
mode tcp
server resin_vpn_1 vpn:443 send-proxy-v2 check-send-proxy port 443
frontend db
mode tcp
bind *:5432
default_backend db
timeout client 1h
backend db
mode tcp
server resin_db_1 db:5432 check port 5432

79
scripts/_keyid.js Normal file
View File

@ -0,0 +1,79 @@
'use strict';
var crypto = require('crypto');
var fs = require('fs');
var base32 = (function() {
// Extracted from https://github.com/chrisumbel/thirty-two
// to avoid having to install packages for this script.
var charTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
var byteTable = [
0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff
];
function quintetCount(buff) {
var quintets = Math.floor(buff.length / 5);
return buff.length % 5 == 0 ? quintets: quintets + 1;
}
return function(plain) {
if (!Buffer.isBuffer(plain)) {
plain = new Buffer(plain);
}
var i = 0;
var j = 0;
var shiftIndex = 0;
var digit = 0;
var encoded = new Buffer(quintetCount(plain) * 8);
/* byte by byte isn't as pretty as quintet by quintet but tests a bit
faster. will have to revisit. */
while(i < plain.length) {
var current = plain[i];
if(shiftIndex > 3) {
digit = current & (0xff >> shiftIndex);
shiftIndex = (shiftIndex + 5) % 8;
digit = (digit << shiftIndex) | ((i + 1 < plain.length) ?
plain[i + 1] : 0) >> (8 - shiftIndex);
i++;
} else {
digit = (current >> (8 - (shiftIndex + 5))) & 0x1f;
shiftIndex = (shiftIndex + 5) % 8;
if(shiftIndex == 0) i++;
}
encoded[j] = charTable.charCodeAt(digit);
j++;
}
for (i = j; i < encoded.length; i++) {
encoded[i] = 0x3d; //'='.charCodeAt(0)
}
return encoded;
}
})();
function joseKeyId(der) {
var hasher = crypto.createHash('sha256');
hasher.update(der);
var b32 = base32(hasher.digest().slice(0, 30)).toString('ascii');
var chunks = [];
for (var i = 0; i < b32.length; i += 4) {
chunks.push(b32.substr(i, 4));
}
return chunks.join(':');
}
var derFilePath = process.argv[2];
var der = fs.readFileSync(derFilePath);
process.stdout.write(joseKeyId(der));

55
scripts/gen-root-ca-cert Executable file
View File

@ -0,0 +1,55 @@
#!/bin/sh
set -e
CN=$1
OUT=${2:-.}
CA="${CN}-ca"
CA_FILE="${OUT}/ca"
CN_FILE="${OUT}/root"
CN_EXPIRY_DAYS=730
CA_EXPIRY_DAYS=3650
usage() {
echo "usage: $0 HOST_NAME [OUT]"
echo
echo " HOST_NAME the domain name the certificate is valid for, eg. example.com"
echo " OUT path to output directory generated files will be placed in"
echo
}
if [ -z "$CN" ]; then
usage
exit 1
fi
cat > "${CN_FILE}.v3.ext" <<STR
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.${CN}
STR
# Create a secret key and CA file for the self-signed CA
openssl genrsa -out "${CA_FILE}.key" 2048 2>/dev/null
openssl req -x509 -new -nodes -sha256 -days $CA_EXPIRY_DAYS -key "${CA_FILE}.key" -subj "/CN=${CA}" -out "${CA_FILE}.pem" 2>/dev/null
# Create a secret key and Certificate Signing Request (CSR) for the domain
openssl genrsa -out "${CN_FILE}.key" 2048 2>/dev/null
openssl req -new -key "${CN_FILE}.key" -subj "/CN=${CN}" -out "${CN_FILE}.csr" 2>/dev/null
# Sign the request with the self-signed CA and extension file
openssl x509 -req -sha256 -days $CN_EXPIRY_DAYS -in "${CN_FILE}.csr" -CA "${CA_FILE}.pem" -CAkey "${CA_FILE}.key" -CAcreateserial -out "${CN_FILE}.pem" -extfile "${CN_FILE}.v3.ext" 2>/dev/null
# Create the custom certificate chain file
cat "${CN_FILE}.pem" "${CA_FILE}.pem" "${CN_FILE}.key" >"${CN_FILE}.chain.pem"
# Cleanup
rm "${CA_FILE}.key" "${CA_FILE}.pem" "${CN_FILE}.key" "${CN_FILE}.pem" "${CN_FILE}.csr" "${CN_FILE}.v3.ext"
echo "ROOT_CA=${CN_FILE}.chain.pem"

42
scripts/gen-token-auth-cert Executable file
View File

@ -0,0 +1,42 @@
#!/bin/sh
set -e
CMD=$0
DIR=$(dirname "$CMD")
CN=$1
OUT=${2:-.}
CERT_FILE="${OUT}/token-auth"
EXPIRY_DAYS=730
usage() {
echo "usage: $0 HOST_NAME [OUT]"
echo
echo " HOST_NAME the domain name the certificate is valid for, eg. example.com"
echo " OUT path to output directory generated files will be placed in"
echo
}
keyid() {
# FIXME: do this in bash or python, not node
nodejs "${DIR}/_keyid.js" "$1"
}
if [ -z "$CN" ]; then
usage
exit 1
fi
openssl ecparam -name prime256v1 -genkey -noout -out "${CERT_FILE}.pem" 2>/dev/null
openssl req -x509 -new -nodes -days "${EXPIRY_DAYS}" -key "${CERT_FILE}.pem" -subj "/CN=api.${CN}" -out "${CERT_FILE}.crt" 2>/dev/null
openssl ec -in "${CERT_FILE}.pem" -pubout -outform DER -out "${CERT_FILE}".der 2>/dev/null
keyid "${CERT_FILE}".der >"${CERT_FILE}".kid
# Cleanup
rm "${CERT_FILE}.der"
echo "PUB=${CERT_FILE}.crt"
echo "KEY=${CERT_FILE}.pem"
echo "KID=${CERT_FILE}.kid"

40
scripts/make-env Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
set -e
HOST_NAME="$1"
ROOT_CA="$2"
TOKEN_AUTH_PUB="$3"
TOKEN_AUTH_KEY="$4"
TOKEN_AUTH_KID="$5"
usage() {
echo "usage: $0 HOST_NAME ROOT_CA TOKEN_AUTH_PUB TOKEN_AUTH_KEY TOKEN_AUTH_KID"
echo
}
randstr() {
LC_CTYPE=C tr -dc A-Za-z0-9 < /dev/urandom | fold -w ${1:-32} | head -n 1
}
b64encode() {
cat "$1" | base64 --wrap=0 2>/dev/null || cat "$1" | base64 --break=0
}
if [ -z "$HOST_NAME" ] || [ -z "$ROOT_CA" ] || [ -z "$TOKEN_AUTH_PUB" ] || [ -z "$TOKEN_AUTH_KEY" ] || [ -z "$TOKEN_AUTH_KID" ]; then
usage
exit 1
fi
cat <<STR
export OPENBALENA_DEBUG=true
export OPENBALENA_PRODUCTION_MODE=false
export OPENBALENA_HOST_NAME=$HOST_NAME
export OPENBALENA_JWT_SECRET=$(randstr 32)
export OPENBALENA_RESINOS_REGISTRY_CODE=$(randstr 32)
export OPENBALENA_ROOT_CA=$(b64encode "$ROOT_CA")
export OPENBALENA_TOKEN_AUTH_PUB=$(b64encode "$TOKEN_AUTH_PUB")
export OPENBALENA_TOKEN_AUTH_KEY=$(b64encode "$TOKEN_AUTH_KEY")
export OPENBALENA_TOKEN_AUTH_KID=$(b64encode "$TOKEN_AUTH_KID")
export OPENBALENA_VPN_SERVICE_API_KEY=$(randstr 32)
STR

36
scripts/patch-hosts Executable file
View File

@ -0,0 +1,36 @@
#!/bin/sh
set -e
CMD=$0
DIR=$(dirname "$CMD")
HOST_NAME=$1
SERVICES="api registry vpn db"
SERVICES="${SERVICES} img devices" # FIXME: remove
usage() {
echo "usage: $0 HOST_NAME"
echo
echo " HOST_NAME the domain name to add host entries for, eg. example.com"
echo
}
if [ -z "$HOST_NAME" ]; then
usage
exit 1
fi
# We need sudo to write to /etc/hosts, so first write to a temp file and then
# append all entries to hosts file.
tmp=$(mktemp --tmpdir openbalena.XXXX)
for service in $SERVICES; do
name="${service}.${HOST_NAME}"
if ! grep "\s$name" /etc/hosts >/dev/null 2>&1 ; then
echo "adding $name"
echo "127.0.0.1 $name" >>$tmp
fi
done
cat $tmp | sudo tee -a /etc/hosts >/dev/null
rm -f $tmp

31
scripts/run-fig-command Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
set -e
CMD=$0
DIR=$(dirname "$CMD")
BASE_DIR=$(dirname "$DIR")
echo_bold() {
printf "\033[1m${@}\033[0m\n"
}
PROJECT_FILE="${BASE_DIR}/.project"
if [ ! -f "$PROJECT_FILE" ]; then
echo_bold 'No project activated. Please create or select an existing one first.'
echo_bold 'See README.md for help.'
exit 1
fi
PROJECT=$(cat "$PROJECT_FILE")
if [ ! -f "${PROJECT}/activate" ]; then
echo_bold 'No project activated. Please create or select an existing one first.'
echo_bold 'See README.md for help.'
exit 1
fi
PROJECT_NAME=$(basename "$PROJECT")
. "${PROJECT}/activate"; docker-compose \
--project-name $PROJECT_NAME \
-f "${BASE_DIR}/compose/services.yml" \
-f "${PROJECT}/docker-compose.yml" \
"$@"

34
scripts/select-project Executable file
View File

@ -0,0 +1,34 @@
#!/bin/sh
set -e
CMD=$0
DIR=$(dirname "$CMD")
BASE_DIR=$(dirname "$DIR")
PROJECT_PATH="$1"
usage() {
echo "usage: $0 PROJECT_PATH"
echo
echo " PROJECT_PATH path to the project; can be relative to open-balena root."
echo
}
if [ -z "$PROJECT_PATH" ]; then
usage
exit 1
fi
PROJECT_DIR=$(realpath "$PROJECT_PATH")
if [ ! -d "$PROJECT_DIR" ]; then
echo 'Project path refers to a directory that does not exist.'
exit 1
fi
if [ ! -f "${PROJECT_DIR}/activate" ]; then
echo 'Project path refers to a directory that is not a valid porject.'
exit 1
fi
echo -n $PROJECT_DIR >"${BASE_DIR}/.project"

58
scripts/start-project Executable file
View File

@ -0,0 +1,58 @@
#!/bin/sh
set -e
CMD=$0
DIR=$(dirname "$CMD")
HOST_NAME=${1:-openbalena.local}
PROJECT_NAME=${2:-demo}
PROJECT_DIR="$(pwd)/${PROJECT_NAME}"
CERTS_DIR="${PROJECT_DIR}/certs"
usage() {
echo "usage: $0 [HOST_NAME [PROJECT_NAME]]"
echo
echo " HOST_NAME the domain name this deployment will run as, eg. example.com. Default is 'openbalena.local'"
echo " PROJECT_NAME a name for the deployment, eg. staging. Default is 'demo'"
echo
}
echo_bold() {
printf "\033[1m${@}\033[0m\n"
}
if [ -d "$PROJECT_DIR" ]; then
echo 'Project directory already exists. Please remove it or specify another project name.'
exit 1
fi
echo_bold "==> Creating new project at: $PROJECT_DIR"
mkdir -p "$PROJECT_DIR" "$CERTS_DIR"
echo_bold "==> Creating root CA cert..."
"${DIR}/gen-root-ca-cert" $HOST_NAME "$CERTS_DIR"
echo_bold "==> Creating token auth cert..."
"${DIR}/gen-token-auth-cert" $HOST_NAME "$CERTS_DIR"
echo_bold "==> Setting up environment..."
cat >"${PROJECT_DIR}/activate" <<STR
$("${DIR}/make-env" \
$HOST_NAME \
"${CERTS_DIR}/root.chain.pem" \
"${CERTS_DIR}/token-auth.crt" \
"${CERTS_DIR}/token-auth.pem" \
"${CERTS_DIR}/token-auth.kid")
STR
echo_bold "==> Adding default compose file..."
echo "version: '2.1'" >"${PROJECT_DIR}/docker-compose.yml"
# FIXME: should be explicitly requested via a flag
echo_bold "==> Patching /etc/hosts..."
"${DIR}/patch-hosts" $HOST_NAME
echo_bold "==> Activating project..."
"${DIR}/select-project" "$PROJECT_DIR"

1
src/README Normal file
View File

@ -0,0 +1 @@
This is the working folder for any specific container you might want to work on.