diff --git a/activemq.sh b/activemq.sh index d14f265..e9956c7 100755 --- a/activemq.sh +++ b/activemq.sh @@ -7,12 +7,9 @@ docker image ls | grep -q java || $(realpath $(dirname "${0}"))/java.sh # Build Docker container docker build -t activemq ${SOURCE_DIR} +cp ${SOURCE_DIR}/etc/init.d/activemq /etc/init.d/activemq +rc-update -u # Configure ActiveMQ mkdir -p /srv/activemq/data chown -R 61616:61616 /srv/activemq/data - -# Configure Solr service -cp ${SOURCE_DIR}/etc/init.d/activemq /etc/init.d/activemq -rc-update add activemq -service activemq start diff --git a/activemq/etc/init.d/activemq b/activemq/etc/init.d/activemq index 2638975..63f66f7 100755 --- a/activemq/etc/init.d/activemq +++ b/activemq/etc/init.d/activemq @@ -3,8 +3,7 @@ description="ActiveMQ docker container" depend() { - need docker net - use dns logger netmount + need docker } start() { diff --git a/basic.sh b/basic.sh index ca4e4e0..ff3ea59 100755 --- a/basic.sh +++ b/basic.sh @@ -27,20 +27,23 @@ cp ${SOURCE_DIR}/etc/conf.d/ntpd /etc/conf.d/ntpd # Create a self-signed certificate mkdir /etc/ssl/private -openssl req -x509 -new -out /etc/ssl/certs/services.pem -keyout /etc/ssl/private/services.key -nodes -days 3654 -subj "/CN=$(hostname)" +openssl req -x509 -new -out /etc/ssl/certs/services.pem -keyout /etc/ssl/private/services.key -nodes -days 7305 -subj "/CN=$(hostname)" chmod 640 /etc/ssl/private/services.key -# Configure acme.sh -cp ${SOURCE_DIR}/usr/local/bin/update-acme.sh /usr/local/bin/update-acme.sh -/usr/local/bin/update-acme.sh - # Configure nginx cp ${SOURCE_DIR}/etc/nginx/nginx.conf /etc/nginx/nginx.conf +# Download and configure acme.sh +mkdir /etc/acme.sh.d +wget https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh -O /usr/bin/acme.sh +sed -i 's|$HOME/.$PROJECT_NAME|/etc/acme.sh.d|' /usr/bin/acme.sh +cp ${SOURCE_DIR}/etc/periodic/daily/acme-sh /etc/periodic/daily/acme-sh +chmod +x /usr/bin/acme.sh + # Copy Spotter resources mkdir /etc/spotter -cp ${SOURCE_DIR}/etc/spotter/apps.json /etc/spotter/apps.json -cp ${SOURCE_DIR}/usr/local/bin/spotter-appmgr /usr/local/bin/spotter-appmgr +cp ${SOURCE_DIR}/srv/config.json /srv/config.json +cp ${SOURCE_DIR}/usr/bin/spotter-appmgr /usr/bin/spotter-appmgr cp -r ${SOURCE_DIR}/srv/portal /srv/portal # Configure services diff --git a/basic/etc/init.d/docker b/basic/etc/init.d/docker index 72a5cbc..cbd9a86 100755 --- a/basic/etc/init.d/docker +++ b/basic/etc/init.d/docker @@ -36,7 +36,5 @@ start_pre() { } start_post() { - until [ -e /var/run/docker.sock ]; do - usleep 100000 - done + ewaitfile 1 /var/run/docker.sock } diff --git a/basic/etc/periodic/daily/acme-sh b/basic/etc/periodic/daily/acme-sh new file mode 100755 index 0000000..5b3d5e3 --- /dev/null +++ b/basic/etc/periodic/daily/acme-sh @@ -0,0 +1,3 @@ +#!/bin/sh + +[ -x /usr/bin/acme.sh ] && /usr/bin/acme.sh --cron >/dev/null diff --git a/basic/etc/spotter/apps.json b/basic/etc/spotter/apps.json deleted file mode 100644 index 7cfd9a6..0000000 --- a/basic/etc/spotter/apps.json +++ /dev/null @@ -1 +0,0 @@ -{"_": {"domain": "spotter.vm", "port": "443"}, "cluster-spotter": {}} diff --git a/basic/srv/config.json b/basic/srv/config.json new file mode 100644 index 0000000..4b7670a --- /dev/null +++ b/basic/srv/config.json @@ -0,0 +1,134 @@ +{ + "apps":{ + "ckan":{ + "host":"ckan", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "crisiscleanup":{ + "host":"cc", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "cts":{ + "host":"cts", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "frontlinesms":{ + "host":"sms", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "gnuhealth":{ + "host":"gh", + "login":"N/A", + "password":"N/A", + "tiles":["gnuhealth-clients"], + "tiles-shown":false + }, + "kanboard":{ + "host":"kb", + "login":"N/A", + "password":"N/A", + "tiles":["kanboard-mobile"], + "tiles-shown":false + }, + "mifosx":{ + "host":"mifosx", + "login":"N/A", + "password":"N/A", + "tiles":["mifosx-mobile"], + "tiles-shown":false + }, + "motech":{ + "host":"motech", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "opendatakit":{ + "host":"odk", + "login":"N/A", + "password":"N/A", + "tiles":["opendatakit-clients"], + "tiles-shown":false + }, + "opendatakit-build":{ + "host":"odkbuild", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "openmapkit":{ + "host":"omk", + "login":"N/A", + "password":"N/A", + "tiles":["geoodk-clients", "openmapkit-clients"], + "tiles-shown":false + }, + "pandora":{ + "host":"pandora", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "sahana":{ + "host":"sahana", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "sahana-demo":{ + "host":"sahana-demo", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "sambro":{ + "host":"sambro", + "login":"N/A", + "password":"N/A", + "tiles":["sambro-mobile"], + "tiles-shown":false + }, + "seeddms":{ + "host":"dms", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "sigmah":{ + "host":"sigmah", + "login":"N/A", + "password":"N/A", + "tiles":[], + "tiles-shown":false + }, + "ushahidi":{ + "host":"ush", + "login":"N/A", + "password":"N/A", + "tiles":["ushahidi-mobile"], + "tiles-shown":false + } + }, + "host":{ + "domain":"spotter.vm", + "port": "443" + } +} diff --git a/basic/srv/portal/css/style.css b/basic/srv/portal/css/style.css index 7bcc3a5..9790c24 100644 --- a/basic/srv/portal/css/style.css +++ b/basic/srv/portal/css/style.css @@ -50,7 +50,7 @@ header p { margin: 0px; } -.c, .c2 { +.c { background-color: white; position: relative; min-width: 365px; @@ -62,9 +62,6 @@ header p { margin-right: 13px; border: solid 1px black; padding: 10px; -} - -.c { display: none; } @@ -73,6 +70,10 @@ header p { width: 95%; } +.visible { + display: initial; +} + .ico { margin-right: 5px; width: 20px; diff --git a/basic/srv/portal/error.html b/basic/srv/portal/error.html new file mode 100644 index 0000000..41a855f --- /dev/null +++ b/basic/srv/portal/error.html @@ -0,0 +1,15 @@ + + +
+ + + + + +Aplikace, ke které se pokoušíte připojit, není dostupná. Nejspíše byla vypnuta správcem serveru.
+ + diff --git a/basic/srv/portal/index.html b/basic/srv/portal/index.html index c055f63..f2c7284 100644 --- a/basic/srv/portal/index.html +++ b/basic/srv/portal/index.html @@ -19,7 +19,7 @@Registr kontaktů asociací, organizací, jednotek zaměstnanců, dobrovolníků, Registr prostředků, materiálních zdrojů určených pro činnost v krizových situacích, logistika krizového zboží ve skladištích, úkrytech, organizace lidských zdrojů, diobrovolníků, mapová vizualizace pro lokalizaci a popis krizové události a mnoho dalších funkcí.
Přístup určený k bezpečnému vyzkoušení aplikace. Zde můžete přidávat i mazat testovací data.
Samostatná instance Sahana EDEN s šablonou SAMBRO.
Mapování krizové pomoci při odstraňování následků katastrof a koordinaci práce. Jde o majetek, ne o lidi.
Repository management a datová analýza pro vytváření otevřených dat.
Sběr dat s pomocí smartphone.
Aplikace pro návrh formulářů
XLSForm - online konverter XLS.
ODK Form Uploader
ODK Validate
Mobilní aplikace
ODK Collect pro Android
ODK Briefcase
Sběr dat s pomocí smartphone.
GeoODK Collect - náhrada papírových dotazníků smartphonem.
Sběr dat s pomocí smartphone.
Mobilní aplikace
ODK Collect pro Android
OpenMapKit pro Android 4.1 a vyšší
Dokument management na dokumentaci a projektovou dokumentaci
Media management na foto a video z krizové události. Tvorba metadat, komentářů, lokalizace v čase a na mapě.
Reakce na krizovou událost. Shromažďujte zprávy od obětí a pracovníků v terénu prostřednictvím SMS, e-mailu, webu, Twitteru.
Usnadňuje tvorbu a řízení projektů s pomocí Kanban metodiky.
Zdravotní a nemocniční informační systém.
Nástroj na rozvojovou, humanitární pomoc a mikrofinancování.
Portable Open Street Map - softwarový balík na offline používání OpenStreet Map v samostatné virtuální image.
Info o Misi a Vizi projektu, včetně kontaktu. Zachovejte data bezpečná a neposkytujte je nepovolaným osobám.
CC 4.0 CZ by TS. Content is based on PD, CC, GNU/GPL. Brand names, trademarks belong to their respective holders.
diff --git a/basic/srv/portal/js/script.js b/basic/srv/portal/js/script.js
index 7a9558e..b51eeb3 100644
--- a/basic/srv/portal/js/script.js
+++ b/basic/srv/portal/js/script.js
@@ -1,13 +1,21 @@
$(function() {
- $.getJSON('apps.json', function(data) {
- var host = data._.domain + (data._.port != '443' ? ':'+data._.port : '')
- $.each(data, function(id, props) {
- var div = $('#'+id).show();
- if (props.hasOwnProperty('url'))
- div.find('h2 a').attr('href', props.url.replace('{host}', host));
- $.each(props, function(key, value) {
- div.find('.'+key).text(value.replace('{host}', host));
+ $.getJSON('config.json', function(data) {
+ $.each(data.apps, function(app, appdata) {
+ if (!appdata['tiles-shown'])
+ return true;
+ var div = $('#'+app).show();
+ div.find('.login').text(appdata.login);
+ div.find('.password').text(appdata.password);
+ $.each(appdata.tiles, function(tile) {
+ $('#'+tile).show();
});
});
+ var host = data.host.domain + (data.host.port != '443' ? ':'+data.host.port : '')
+ $('a').each(function(){
+ $(this).attr('href', $(this).attr('href').replace('{host}', host));
+ });
+ $('span').each(function(){
+ $(this).text($(this).text().replace('{host}', host));
+ });
});
});
diff --git a/basic/usr/bin/spotter-appmgr b/basic/usr/bin/spotter-appmgr
new file mode 100755
index 0000000..ec7baed
--- /dev/null
+++ b/basic/usr/bin/spotter-appmgr
@@ -0,0 +1,317 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import argparse
+import json
+import os
+import subprocess
+
+CONF_FILE = '/srv/config.json'
+ISSUE_FILE = '/etc/issue'
+NGINX_DIR = '/etc/nginx/conf.d'
+
+NGINX_TEMPLATE = '''server {{
+ listen [::]:{port} ssl http2;
+ server_name {host}.{domain};
+
+ access_log /var/log/nginx/{app}.access.log;
+ error_log /var/log/nginx/{app}.error.log;
+
+ location / {{
+ proxy_pass http://{ip}:8080;
+ }}
+
+ error_page 502 /errror.html;
+ location /error.html {{
+ root /srv/portal;
+ }}
+}}
+'''
+
+NGINX_DEFAULT_TEMPLATE = '''server {{
+ listen [::]:80 default_server ipv6only=off;
+
+ location / {{
+ return 301 https://$host:{port}$request_uri;
+ }}
+ location /.well-known/acme-challenge/ {{
+ root /etc/acme.sh.d;
+ }}
+}}
+
+server {{
+ listen [::]:{port} ssl http2 default_server ipv6only=off;
+ root /srv/portal;
+ index index.html;
+
+ location / {{
+ try_files $uri $uri/ =404;
+ }}
+ location /config.json {{
+ alias /srv/config.json;
+ }}
+
+ error_page 404 /error.html;
+}}
+'''
+
+ISSUE_TEMPLATE = '''
+\x1b[1;32m _____ _ _ __ ____ __
+ / ____| | | | | \\\\ \\\\ / / \\\\/ |
+ | (___ _ __ ___ | |_| |_ ___ _ _\\\\ \\\\ / /| \\\\ / |
+ \\\\___ \\\\| '_ \\\\ / _ \\\\| __| __/ _ \\\\ '__\\\\ \\\\/ / | |\\\\/| |
+ ____) | |_) | (_) | |_| || __/ | \\\\ / | | | |
+ |_____/| .__/ \\\\___/ \\\\__|\\\\__\\\\___|_| \\\\/ |_| |_|
+ | |
+ |_|\x1b[0m
+
+
+
+
+ \x1b[1;33mUPOZORNĚNÍ:\x1b[0m Neoprávněný přístup k tomuto zařízení je zakázán.
+ Musíte mít výslovné oprávnění k přístupu nebo konfiguraci tohoto zařízení.
+ Neoprávněné pokusy a kroky k přístupu nebo používání tohoto systému mohou mít
+ za následek občanské nebo trestní sankce.
+
+
+ \x1b[1;33mCAUTION:\x1b[0m Unauthozired access to this device is prohibited.
+ You must have explicit, authorized permission to access or configure this
+ device. Unauthorized attempts and actions to access or use this system may
+ result in civil or criminal penalties.
+
+
+
+
+ Pro přístup k aplikacím otevřete URL \x1b[1mhttps://{host}\x1b[0m ve Vašem
+ internetovém prohlížeči.
+
+
+
+
+
+
+\x1b[0;30m
+'''
+
+class SpotterManager:
+ def __init__(self):
+ # Load JSON configuration
+ with open(CONF_FILE, 'r') as f:
+ self.conf = json.load(f)
+ self.domain = self.conf['host']['domain']
+ self.port = self.conf['host']['port']
+
+ def save_conf(self):
+ # Save a sorted JSON configuration object with indentation
+ with open(CONF_FILE, 'w') as f:
+ json.dump(self.conf, f, sort_keys=True, indent=4)
+
+ def update_login(self, app, login, password):
+ # Update login and password for an app in the configuration
+ if login is not None:
+ self.conf['apps'][app]['login'] = login
+ if password is not None:
+ self.conf['apps'][app]['password'] = password
+ self.save_conf()
+
+ def show_tiles(self, app):
+ # Update tiles-shown for the app in the configuration
+ self.conf['apps'][app]['tiles-shown'] = True
+ self.save_conf()
+
+ def hide_tiles(self, app):
+ # Update tiles-shown for the app in the configuration
+ self.conf['apps'][app]['tiles-shown'] = False
+ self.save_conf()
+
+ def start_app(self, app):
+ # Start the actual app service
+ subprocess.call(['/sbin/service', app, 'start'])
+
+ def stop_app(self, app):
+ # Stop the actual app service
+ subprocess.call(['/sbin/service', app, 'stop'])
+ # Stop the app service's dependencies if they are not used by any other running app
+ deps = self.build_deps_tree()
+ for dep in self.get_app_deps(app):
+ if False not in [self.is_app_started(d) for d in deps[dep]]:
+ subprocess.call(['/sbin/service', dep, 'stop'])
+
+ def build_deps_tree(self):
+ # Fisrt, build a dictionary of {app: [needs]}
+ needs = {}
+ for app in self.conf['apps']:
+ needs[app] = self.get_app_deps(app)
+ # Then reverse it to {need: [apps]}
+ deps = {}
+ for app, need in needs.iteritems():
+ for n in need:
+ deps.setdefault(n, []).append(app)
+ return deps
+
+ def get_app_deps(self, app):
+ # Get "needs" line from init script and split it to list, skipping first two elements (docker, net)
+ try:
+ with open(os.path.join('/etc/init.d', app), 'r') as f:
+ return [l.split()[2:] for l in f.readlines() if l.startswith('\tneed')][0]
+ except:
+ return []
+
+ def is_app_started(self, app):
+ # Check OpenRC service status without calling any binary
+ return os.path.exists(os.path.join('/run/openrc/started', app))
+
+ def enable_autostart(self, app):
+ # Add the app to OpenRC default runlevel
+ subprocess.call(['/sbin/rc-update', 'add', app])
+
+ def disable_autostart(self, app):
+ # Remove the app from OpenRC default runlevel
+ subprocess.call(['/sbin/rc-update', 'del', app])
+
+ def register_proxy(self, app):
+ # Rebuild nginx configuration using an actual IP of referenced app container
+ with open(os.path.join(NGINX_DIR, '{}.conf'.format(app)), 'w') as f:
+ f.write(NGINX_TEMPLATE.format(app=app, host=self.conf['apps'][app]['host'], ip=self.get_container_ip(app), domain=self.domain, port=self.port))
+ subprocess.call(['/sbin/service', 'nginx', 'reload'])
+
+ def unregister_proxy(self, app):
+ # Remove nginx configuration to prevent proxy mismatch when the container IP is reassigned to another container
+ nginx_conf = os.path.join(NGINX_DIR, '{}.conf'.format(app))
+ if os.path.exists(nginx_conf):
+ os.unlink(nginx_conf)
+ subprocess.call(['/sbin/service', 'nginx', 'reload'])
+
+ def get_container_ip(self, app):
+ # Return an IP address of a container. If the container is not running, return localhost address instead
+ try:
+ return subprocess.check_output(['/usr/bin/docker', 'inspect', '-f', '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}', app]).strip()
+ except:
+ return '127.0.0.1'
+
+ def update_domain(self, domain, port):
+ self.domain = self.conf['host']['domain'] = domain
+ self.port = self.conf['host']['port'] = port
+ self.save_conf()
+ self.rebuild_nginx()
+ self.rebuild_issue()
+ self.restart_apps()
+
+ def rebuild_nginx(self):
+ # Remove all nginx config files to prevent errors during reloads invoked by app restarts
+ for f in os.listdir(NGINX_DIR):
+ os.unlink(os.path.join(NGINX_DIR, f))
+ # Rebuild nginx config for the portal app and restart nginx to properly bind the new listen port
+ with open(os.path.join(NGINX_DIR, 'default.conf'), 'w') as f:
+ f.write(NGINX_DEFAULT_TEMPLATE.format(port=self.port))
+ subprocess.call(['/sbin/service', 'nginx', 'restart'])
+
+ def rebuild_issue(self):
+ # Compile the HTTPS host displayed in terminal banner
+ host = self.domain
+ # If the dummy host is used, take an IP address of a primary interface instead
+ if self.domain == 'spotter.vm':
+ host = subprocess.check_output(['ip', 'route', 'get', '1']).split()[-1]
+ # Show port number only when using the non-default HTTPS port
+ if self.port != '443':
+ host = ':{}'.format(self.port)
+ # Rebuild the terminal banner
+ with open(ISSUE_FILE, 'w') as f:
+ f.write(ISSUE_TEMPLATE.format(host=host))
+
+ def restart_apps(self):
+ for app in self.conf['apps']:
+ # Check if a script for internal update of URL in the app exists and is executable and run it
+ script_path = os.path.join('/srv', app, 'update-url.sh')
+ if os.path.exists(script_path) and os.access(script_path, os.X_OK):
+ subprocess.call([script_path, '{}.{}'.format(self.conf['apps'][app]['host'], self.domain), self.port])
+ # If the app is currently running, restart the app service
+ if self.is_app_started(app):
+ subprocess.call(['/sbin/service', app, 'restart'])
+
+ def request_cert(self, email):
+ # Compile an acme.sh command for certificate requisition
+ cmd = ['/usr/bin/acme.sh', '--issue', '-d', self.domain]
+ for app in self.conf['apps']:
+ cmd += ['-d', '{}.{}'.format(self.conf['apps'][app]['host'], self.domain)]
+ cmd += ['-w', '/etc/acme.sh.d', '--accountemail', email]
+ # Request the certificate. If the requisition command fails, CalledProcessError will be raised
+ subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+ # Install the issued certificate
+ subprocess.call(['/usr/bin/acme.sh', '--installcert', '-d', self.domain, '--keypath', '/etc/ssl/private/services.key', '--fullchainpath', '/etc/ssl/certs/services.pem', '--reloadcmd', 'service nginx reload'])
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Spotter VM application manager')
+ subparsers = parser.add_subparsers()
+
+ parser_update_login = subparsers.add_parser('update-login', help='Updates application login')
+ parser_update_login.set_defaults(action='update-login')
+ parser_update_login.add_argument('app', help='Application name')
+ parser_update_login.add_argument('login', help='Administrative login')
+ parser_update_login.add_argument('password', help='Administrative password')
+
+ parser_show_tiles = subparsers.add_parser('show-tiles', help='Shows application tiles in Portal')
+ parser_show_tiles.set_defaults(action='show-tiles')
+ parser_show_tiles.add_argument('app', help='Application name')
+
+ parser_hide_tiles = subparsers.add_parser('hide-tiles', help='Hides application tiles in Portal')
+ parser_hide_tiles.set_defaults(action='hide-tiles')
+ parser_hide_tiles.add_argument('app', help='Application name')
+
+ parser_start_app = subparsers.add_parser('start-app', help='Start application including it\'s dependencies')
+ parser_start_app.set_defaults(action='start-app')
+ parser_start_app.add_argument('app', help='Application name')
+
+ parser_stop_app = subparsers.add_parser('stop-app', help='Stops application including it\'s dependencies if they are not used by another running application')
+ parser_stop_app.set_defaults(action='stop-app')
+ parser_stop_app.add_argument('app', help='Application name')
+
+ parser_enable_autostart = subparsers.add_parser('enable-autostart', help='Enables application autostart')
+ parser_enable_autostart.set_defaults(action='enable-autostart')
+ parser_enable_autostart.add_argument('app', help='Application name')
+
+ parser_disable_autostart = subparsers.add_parser('disable-autostart', help='Disables application autostart')
+ parser_disable_autostart.set_defaults(action='disable-autostart')
+ parser_disable_autostart.add_argument('app', help='Application name')
+
+ parser_register_proxy = subparsers.add_parser('register-proxy', help='Rebuilds nginx proxy target for an application container')
+ parser_register_proxy.set_defaults(action='register-proxy')
+ parser_register_proxy.add_argument('app', help='Application name')
+
+ parser_unregister_proxy = subparsers.add_parser('unregister-proxy', help='Removes nginx proxy target for an application container')
+ parser_unregister_proxy.set_defaults(action='unregister-proxy')
+ parser_unregister_proxy.add_argument('app', help='Application name')
+
+ parser_update_domain = subparsers.add_parser('update-domain', help='Rebuilds domain structure of VM with new domain name and new HTTPS port')
+ parser_update_domain.set_defaults(action='update-domain')
+ parser_update_domain.add_argument('domain', help='Domain name')
+ parser_update_domain.add_argument('port', help='HTTPS port')
+
+ parser_request_cert = subparsers.add_parser('request-cert', help='Requests and installs Let\'s Encrypt certificate for currently set domain')
+ parser_request_cert.set_defaults(action='request-cert')
+ parser_request_cert.add_argument('email', help='Email address to receive certificate notifications')
+
+ args = parser.parse_args()
+ sm = SpotterManager()
+ if args.action == 'update-login':
+ sm.update_login(args.app, args.login, args.password)
+ elif args.action == 'show-tiles':
+ sm.show_tiles(args.app)
+ elif args.action == 'hide-tiles':
+ sm.hide_tiles(args.app)
+ elif args.action == 'start-app':
+ sm.start_app(args.app)
+ elif args.action == 'stop-app':
+ sm.stop_app(args.app)
+ elif args.action == 'enable-autostart':
+ sm.enable_autostart(args.app)
+ elif args.action == 'disable-autostart':
+ sm.disable_autostart(args.app)
+ elif args.action == 'register-proxy':
+ sm.register_proxy(args.app)
+ elif args.action == 'unregister-proxy':
+ sm.unregister_proxy(args.app)
+ elif args.action == 'update-domain':
+ sm.update_domain(args.domain, args.port)
+ elif args.action == 'request-cert':
+ sm.request_cert(args.email)
diff --git a/basic/usr/local/bin/spotter-appmgr b/basic/usr/local/bin/spotter-appmgr
deleted file mode 100755
index 0c6779b..0000000
--- a/basic/usr/local/bin/spotter-appmgr
+++ /dev/null
@@ -1,197 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-import argparse
-import json
-import os
-import subprocess
-
-CONF_FILE = '/etc/spotter/apps.json'
-ISSUE_FILE = '/etc/issue'
-NGINX_DIR = '/etc/nginx/conf.d'
-
-NGINX_TEMPLATE = '''server {{
- listen [::]:{port} ssl http2;
- server_name {app}.{domain};
-
- access_log /var/log/nginx/{app}.access.log;
- error_log /var/log/nginx/{app}.error.log;
-
- location / {{
- proxy_pass http://{ip}:8080;
- }}
-}}
-'''
-
-NGINX_DEFAULT_TEMPLATE = '''server {{
- listen [::]:80 default_server ipv6only=off;
-
- location / {{
- return 301 https://$host:{port}$request_uri;
- }}
- location /.well-known/acme-challenge/ {{
- root /etc/acme.sh.d;
- }}
-}}
-
-server {{
- listen [::]:{port} ssl http2 default_server ipv6only=off;
- root /srv/portal;
- index index.html;
-
- location / {{
- try_files $uri $uri/ =404;
- }}
- location /apps.json {{
- alias /etc/spotter/apps.json;
- }}
-}}
-'''
-
-ISSUE_TEMPLATE = '''
-\x1b[1;32m _____ _ _ __ ____ __
- / ____| | | | | \\\\ \\\\ / / \\\\/ |
- | (___ _ __ ___ | |_| |_ ___ _ _\\\\ \\\\ / /| \\\\ / |
- \\\\___ \\\\| '_ \\\\ / _ \\\\| __| __/ _ \\\\ '__\\\\ \\\\/ / | |\\\\/| |
- ____) | |_) | (_) | |_| || __/ | \\\\ / | | | |
- |_____/| .__/ \\\\___/ \\\\__|\\\\__\\\\___|_| \\\\/ |_| |_|
- | |
- |_|\x1b[0m
-
-
-
-
- \x1b[1;33mUPOZORNĚNÍ:\x1b[0m Neoprávněný přístup k tomuto zařízení je zakázán.
- Musíte mít výslovné oprávnění k přístupu nebo konfiguraci tohoto zařízení.
- Neoprávněné pokusy a kroky k přístupu nebo používání tohoto systému mohou mít
- za následek občanské nebo trestní sankce.
-
-
- \x1b[1;33mCAUTION:\x1b[0m Unauthozired access to this device is prohibited.
- You must have explicit, authorized permission to access or configure this
- device. Unauthorized attempts and actions to access or use this system may
- result in civil or criminal penalties.
-
-
-
-
- Pro přístup k aplikacím otevřete URL \x1b[1mhttps://{host}/\x1b[0m ve Vašem
- internetovém prohlížeči.
-
-
-
-
-
-
-\x1b[0;30m
-'''
-
-class SpotterManager:
- def __init__(self):
- self.conf = {}
- with open(CONF_FILE, 'r') as f:
- self.conf = json.load(f)
- self.domain = self.conf["_"]["domain"]
- self.port = self.conf["_"]["port"]
-
- def save_conf(self):
- with open(CONF_FILE, 'w') as f:
- json.dump(self.conf, f)
-
- def add_app(self, app, args):
- self.add_app_to_conf(app, args)
- if args.url:
- self.update_app_conf(app)
-
- def add_app_to_conf(self, app, args):
- self.conf[app] = {}
- for key in ('url', 'login', 'password'):
- value = getattr(args, key)
- if value:
- self.conf[app][key] = value
- if args.property:
- for key, value in args.property:
- self.conf[app][key] = value
- self.save_conf()
-
- def update_app_conf(self, app):
- script_path = os.path.join('/srv', app, 'update-url.sh')
- if os.path.exists(script_path) and os.access(script_path, os.X_OK):
- host = '{}.{}'.format(app, self.domain)
- subprocess.call([script_path, host, self.port])
- subprocess.call(['service', app, 'restart'])
-
- def update_proxy(self, app):
- self.add_app_to_nginx(app)
- subprocess.call(['service', 'nginx', 'reload'])
-
- def add_app_to_nginx(self, app):
- ip = get_container_ip(app)
- with open(os.path.join(NGINX_DIR, '{}.conf'.format(app)), 'w') as f:
- f.write(NGINX_TEMPLATE.format(app=app, ip=ip, domain=self.domain, port=self.port))
-
- def update_domain(self, domain, port):
- self.domain = self.conf["_"]["domain"] = domain
- self.port = self.conf["_"]["port"] = port
- self.save_conf()
- self.update_app_confs()
- self.rebuild_nginx()
- self.rebuild_issue()
- subprocess.call(['service', 'nginx', 'restart'])
-
- def update_app_confs(self):
- for app in self.conf.iteritems():
- if 'url' in app[1]:
- self.update_app_conf(app[0])
-
- def rebuild_nginx(self):
- for f in os.listdir(NGINX_DIR):
- os.unlink(os.path.join(NGINX_DIR, f))
- with open(os.path.join(NGINX_DIR, 'default.conf'), 'w') as f:
- f.write(NGINX_DEFAULT_TEMPLATE.format(port=self.port))
- for app in self.conf.iteritems():
- if 'url' in app[1]:
- self.add_app_to_nginx(app[0])
-
- def rebuild_issue(self):
- host = self.domain
- if self.port != '443':
- host = '{}:{}'.format(host, self.port)
- with open(ISSUE_FILE, 'w') as f:
- f.write(ISSUE_TEMPLATE.format(host=host))
-
-def get_container_ip(app):
- try:
- return subprocess.check_output(['docker', 'inspect', '-f', '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}', app]).strip()
- except:
- return '127.0.0.1'
-
-if __name__ == '__main__':
- parser = argparse.ArgumentParser(description='Spotter VM application manager')
- subparsers = parser.add_subparsers()
-
- parser_add_app = subparsers.add_parser('add-app', help='Registers a new application')
- parser_add_app.set_defaults(action='add-app')
- parser_add_app.add_argument('app', help='Application name')
- parser_add_app.add_argument('url', nargs='?', help='URL to the application. Use "{host}" as a host placeholder')
- parser_add_app.add_argument('login', nargs='?', help='Administrative login')
- parser_add_app.add_argument('password', nargs='?', help='Administrative password')
- parser_add_app.add_argument('-p', '--property', nargs=2, action='append', help='Add arbitrary key-value to the application properties')
-
- parser_update_proxy = subparsers.add_parser('update-proxy', help='Updates nginx proxy target for an application container')
- parser_update_proxy.set_defaults(action='update-proxy')
- parser_update_proxy.add_argument('app', help='Application name')
-
- parser_update_domain = subparsers.add_parser('update-domain', help='Rebuilds domain structure of VM with new domain name and new HTTPS port')
- parser_update_domain.set_defaults(action='update-domain')
- parser_update_domain.add_argument('domain', help='Domain name')
- parser_update_domain.add_argument('port', help='HTTPS port')
-
- args = parser.parse_args()
- sm = SpotterManager()
- if args.action == 'add-app':
- sm.add_app(args.app, args)
- elif args.action == 'update-proxy':
- sm.update_proxy(args.app)
- elif args.action == 'update-domain':
- sm.update_domain(args.domain, args.port)
diff --git a/basic/usr/local/bin/update-acme.sh b/basic/usr/local/bin/update-acme.sh
deleted file mode 100755
index 3f22c71..0000000
--- a/basic/usr/local/bin/update-acme.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-mkdir -p /etc/acme.sh.d
-wget https://raw.githubusercontent.com/Neilpang/acme.sh/master/acme.sh -O /usr/local/bin/acme.sh
-sed -i 's/\$HOME\/.\$PROJECT_NAME/\/etc\/acme.sh.d/' /usr/local/bin/acme.sh
-chmod +x /usr/local/bin/acme.sh
diff --git a/ccleanup.sh b/ccleanup.sh
index 3874722..3184e6b 100755
--- a/ccleanup.sh
+++ b/ccleanup.sh
@@ -6,9 +6,12 @@ SOURCE_DIR=$(realpath $(dirname "${0}"))/ccleanup
docker image ls | grep -q postfix || $(realpath $(dirname "${0}"))/postfix.sh
docker image ls | grep -q postgres || $(realpath $(dirname "${0}"))/postgres.sh
docker image ls | grep -q ruby || $(realpath $(dirname "${0}"))/ruby.sh
+service postgres start
# Build Docker container
docker build -t ccleanup ${SOURCE_DIR}
+cp ${SOURCE_DIR}/etc/init.d/ccleanup /etc/init.d/ccleanup
+rc-update -u
# Create database
export CCLEANUP_PWD=$(head -c 18 /dev/urandom | base64)
@@ -28,17 +31,10 @@ envsubst <${SOURCE_DIR}/srv/ccleanup/conf/database.yml >/srv/ccleanup/conf/datab
cp ${SOURCE_DIR}/srv/ccleanup/conf/boot.rb /srv/ccleanup/conf/boot.rb
cp ${SOURCE_DIR}/srv/ccleanup/conf/initializers/devise.rb /srv/ccleanup/conf/initializers/devise.rb
cp ${SOURCE_DIR}/srv/ccleanup/conf/environments/production.rb /srv/ccleanup/conf/environments/production.rb
+spotter-appmgr update-login ccleanup "${CCLEANUP_ADMIN_EMAIL}" "${CCLEANUP_ADMIN_PWD}"
# Populate database
envsubst <${SOURCE_DIR}/srv/ccleanup/db/seeds.rb >/tmp/seeds.rb
docker run --rm -h ccleanup --link postgres -v /srv/ccleanup/conf:/srv/ccleanup/config ccleanup rake db:schema:load
docker run --rm -h ccleanup --link postgres -v /srv/ccleanup/conf:/srv/ccleanup/config -v /tmp/seeds.rb:/srv/ccleanup/db/seeds.rb ccleanup rake db:seed
rm /tmp/seeds.rb
-
-# Create CrisisCleanup service
-cp ${SOURCE_DIR}/etc/init.d/ccleanup /etc/init.d/ccleanup
-rc-update add ccleanup
-service ccleanup start
-
-# Add application definition
-spotter-appmgr add-app ccleanup "https://ccleanup.{host}/" "${CCLEANUP_ADMIN_EMAIL}" "${CCLEANUP_ADMIN_PWD}"
diff --git a/ccleanup/etc/init.d/ccleanup b/ccleanup/etc/init.d/ccleanup
index 19f733d..16ce925 100755
--- a/ccleanup/etc/init.d/ccleanup
+++ b/ccleanup/etc/init.d/ccleanup
@@ -3,8 +3,7 @@
description="Crisis Cleanup docker container"
depend() {
- need docker net postgres
- use dns logger netmount postfix
+ need docker postfix postgres
}
start() {
@@ -18,7 +17,11 @@ start() {
}
start_post() {
- /usr/local/bin/spotter-appmgr update-proxy ccleanup
+ /usr/bin/spotter-appmgr register-proxy ccleanup
+}
+
+stop_pre() {
+ /usr/bin/spotter-appmgr unregister-proxy ccleanup
}
stop() {
diff --git a/ckan.sh b/ckan.sh
index 3b74f05..2035846 100755
--- a/ckan.sh
+++ b/ckan.sh
@@ -8,9 +8,14 @@ docker image ls | grep -q postfix || $(realpath $(dirname "${0}"))/postfix.sh
docker image ls | grep -q postgres || $(realpath $(dirname "${0}"))/postgres.sh
docker image ls | grep -q redis || $(realpath $(dirname "${0}"))/redis.sh
docker image ls | grep -q solr || $(realpath $(dirname "${0}"))/solr.sh
+service postgres start
+service redis start
+service solr start
# Build Docker container
docker build -t ckan ${SOURCE_DIR}
+cp ${SOURCE_DIR}/etc/init.d/ckan /etc/init.d/ckan
+rc-update -u
# Create database
export CKAN_PWD=$(head -c 18 /dev/urandom | base64)
@@ -51,14 +56,7 @@ export CKAN_ADMIN_PWD=$(head -c 12 /dev/urandom | base64)
export CKAN_ADMIN_HASH=$(docker run --rm ckan python -c "from passlib.hash import pbkdf2_sha512;print pbkdf2_sha512.encrypt('${CKAN_ADMIN_PWD}')")
export CKAN_ADMIN_EMAIL="admin@example.com"
envsubst <${SOURCE_DIR}/adminpwd.sql | docker exec -i postgres psql ckan
-
-# Configure CKAN service
-cp ${SOURCE_DIR}/etc/init.d/ckan /etc/init.d/ckan
-rc-update add ckan
-service ckan start
+spotter-appmgr update-login ckan "${CKAN_ADMIN_USER}" "${CKAN_ADMIN_PWD}"
# Install cron job
cp ${SOURCE_DIR}/etc/periodic/hourly/ckan /etc/periodic/hourly/ckan
-
-# Add application definition
-spotter-appmgr add-app ckan "https://ckan.{host}/" "${CKAN_ADMIN_USER}" "${CKAN_ADMIN_PWD}"
diff --git a/ckan/etc/init.d/ckan b/ckan/etc/init.d/ckan
index c1a88d6..b07e216 100755
--- a/ckan/etc/init.d/ckan
+++ b/ckan/etc/init.d/ckan
@@ -3,9 +3,7 @@
description="CKAN docker container"
depend() {
- need docker net postgres
- use dns logger netmount postfix
- after ckandp redis solr
+ need docker ckandp postfix postgres redis solr
}
start() {
@@ -23,7 +21,11 @@ start() {
}
start_post() {
- /usr/local/bin/spotter-appmgr update-proxy ckan
+ /usr/bin/spotter-appmgr register-proxy ckan
+}
+
+stop_pre() {
+ /usr/bin/spotter-appmgr unregister-proxy ckan
}
stop() {
diff --git a/ckan/srv/ckan/conf/ckan.ini b/ckan/srv/ckan/conf/ckan.ini
index 39818c6..e5c67d9 100644
--- a/ckan/srv/ckan/conf/ckan.ini
+++ b/ckan/srv/ckan/conf/ckan.ini
@@ -56,7 +56,7 @@ ckan.datastore.default_fts_index_method = gist
## Site Settings
-ckan.site_url = http://127.0.0.1
+ckan.site_url = https://ckan.spotter.vm
#ckan.use_pylons_response_cleanup_middleware = true
## Authorization Settings
diff --git a/ckandp.sh b/ckandp.sh
index 5619449..c1b7dc5 100755
--- a/ckandp.sh
+++ b/ckandp.sh
@@ -4,14 +4,11 @@ SOURCE_DIR=$(realpath $(dirname "${0}"))/ckandp
# Build Docker container
docker build -t ckandp ${SOURCE_DIR}
+cp ${SOURCE_DIR}/etc/init.d/ckandp /etc/init.d/ckandp
+rc-update -u
# Configure CKAN DataPusher
mkdir -p /srv/ckandp/conf /srv/ckandp/data
cp ${SOURCE_DIR}/srv/ckandp/conf/datapusher.wsgi /srv/ckandp/conf/datapusher.wsgi
cp ${SOURCE_DIR}/srv/ckandp/conf/datapusher_settings.py /srv/ckandp/conf/datapusher_settings.py
chown -R 8004:8004 /srv/ckandp/data
-
-# Configure CKAN DataPusher service
-cp ${SOURCE_DIR}/etc/init.d/ckandp /etc/init.d/ckandp
-rc-update add ckandp
-service ckandp start
diff --git a/ckandp/etc/init.d/ckandp b/ckandp/etc/init.d/ckandp
index a41cfcc..080211c 100755
--- a/ckandp/etc/init.d/ckandp
+++ b/ckandp/etc/init.d/ckandp
@@ -3,8 +3,7 @@
description="CKAN DataPusher docker container"
depend() {
- need docker net
- use dns logger netmount
+ need docker
}
start() {
diff --git a/cts.sh b/cts.sh
index ab714de..6e0fc67 100755
--- a/cts.sh
+++ b/cts.sh
@@ -4,9 +4,12 @@ SOURCE_DIR=$(realpath $(dirname "${0}"))/cts
# Check prerequisites
docker image ls | grep -q postgres || $(realpath $(dirname "${0}"))/postgres.sh
+service postgres start
# Build Docker container
docker build -t cts ${SOURCE_DIR}
+cp ${SOURCE_DIR}/etc/init.d/cts /etc/init.d/cts
+rc-update -u
# Create database
export CTS_PWD=$(head -c 18 /dev/urandom | base64)
@@ -35,11 +38,4 @@ export CTS_ADMIN_PWD=$(head -c 12 /dev/urandom | base64)
export CTS_ADMIN_HASH=$(docker run --rm -h cts -v /srv/cts/conf:/srv/cts/cts/settings cts python -c "from django.contrib.auth.hashers import make_password; print make_password('${CTS_ADMIN_PWD}')")
export CTS_ADMIN_SECRET=$(head -c 12 /dev/urandom | sha256sum | cut -c1-13)
envsubst <${SOURCE_DIR}/adminpwd.sql | docker exec -i postgres psql cts
-
-# Create CTS service
-cp ${SOURCE_DIR}/etc/init.d/cts /etc/init.d/cts
-rc-update add cts
-service cts start
-
-# Add application definition
-spotter-appmgr add-app cts "https://cts.{host}/" "${CTS_ADMIN_EMAIL}" "${CTS_ADMIN_PWD}"
+spotter-appmgr update-login cts "${CTS_ADMIN_EMAIL}" "${CTS_ADMIN_PWD}"
diff --git a/cts/etc/init.d/cts b/cts/etc/init.d/cts
index c87bb4d..028b1d8 100755
--- a/cts/etc/init.d/cts
+++ b/cts/etc/init.d/cts
@@ -3,8 +3,7 @@
description="CTS docker container"
depend() {
- need docker net postgres
- use dns logger netmount
+ need docker postgres
}
start() {
@@ -17,7 +16,11 @@ start() {
}
start_post() {
- /usr/local/bin/spotter-appmgr update-proxy cts
+ /usr/bin/spotter-appmgr register-proxy cts
+}
+
+stop_pre() {
+ /usr/bin/spotter-appmgr unregister-proxy cts
}
stop() {
diff --git a/flsms.sh b/flsms.sh
index 0f8828b..771608d 100755
--- a/flsms.sh
+++ b/flsms.sh
@@ -7,20 +7,15 @@ docker image ls | grep -q java || $(realpath $(dirname "${0}"))/java.sh
# Build Docker container
docker build -t flsms ${SOURCE_DIR}
+cp ${SOURCE_DIR}/etc/init.d/flsms /etc/init.d/flsms
+rc-update -u
# Configure FrontlineSMS
mkdir -p /srv/flsms/data
-export FLSMS_ADMIN_USER=admin
+export FLSMS_ADMIN_USER="admin"
export FLSMS_ADMIN_PWD=$(head -c 12 /dev/urandom | base64)
export FLSMS_ADMIN_USER_HASH=$(echo -n "${FLSMS_ADMIN_USER}" | base64)
export FLSMS_ADMIN_PWD_HASH=$(echo -n "${FLSMS_ADMIN_PWD}" | base64)
envsubst <${SOURCE_DIR}/srv/flsms/data/app-settings.properties >/srv/flsms/data/app-settings.properties
chown -R 8018:8018 /srv/flsms/data
-
-# Create FrontlineSMS service
-cp ${SOURCE_DIR}/etc/init.d/flsms /etc/init.d/flsms
-rc-update add flsms
-service flsms start
-
-# Add application definition
-spotter-appmgr add-app flsms "https://flsms.{host}/" "${FLSMS_ADMIN_USER}" "${FLSMS_ADMIN_PWD}"
+spotter-appmgr update-login flsms "${FLSMS_ADMIN_USER}" "${FLSMS_ADMIN_PWD}"
diff --git a/flsms/etc/init.d/flsms b/flsms/etc/init.d/flsms
index 78be8fb..93c2185 100755
--- a/flsms/etc/init.d/flsms
+++ b/flsms/etc/init.d/flsms
@@ -3,8 +3,7 @@
description="FrontlineSMS docker container"
depend() {
- need docker net
- use dns logger netmount
+ need docker
}
start() {
@@ -16,7 +15,11 @@ start() {
}
start_post() {
- /usr/local/bin/spotter-appmgr update-proxy flsms
+ /usr/bin/spotter-appmgr register-proxy flsms
+}
+
+stop_pre() {
+ /usr/bin/spotter-appmgr unregister-proxy flsms
}
stop() {
diff --git a/gnuhealth.sh b/gnuhealth.sh
index 1882938..8d448cb 100755
--- a/gnuhealth.sh
+++ b/gnuhealth.sh
@@ -5,9 +5,12 @@ SOURCE_DIR=$(realpath $(dirname "${0}"))/gnuhealth
# Check prerequisites
docker image ls | grep -q postfix || $(realpath $(dirname "${0}"))/postfix.sh
docker image ls | grep -q postgres || $(realpath $(dirname "${0}"))/postgres.sh
+service postgres start
# Build Docker container
docker build -t gnuhealth ${SOURCE_DIR}
+cp ${SOURCE_DIR}/etc/init.d/gnuhealth /etc/init.d/gnuhealth
+rc-update -u
# Create databases
export GNUHEALTH_PWD=$(head -c 18 /dev/urandom | base64 | tr -d '/+=')
@@ -18,21 +21,14 @@ mkdir -p /srv/gnuhealth/conf/
envsubst <${SOURCE_DIR}/srv/gnuhealth/conf/trytond.conf >/srv/gnuhealth/conf/trytond.conf
# Populate database
+export GNUHEALTH_ADMIN_USER="admin"
export GNUHEALTH_ADMIN_PWD=$(head -c 12 /dev/urandom | base64)
echo ${GNUHEALTH_ADMIN_PWD} >/tmp/.adminpwd
docker run --rm -h gnuhealth --link postgres -v /srv/gnuhealth/conf:/srv/gnuhealth/gnuhealth/tryton/server/config -v /tmp/.adminpwd:/tmp/.adminpwd -e TRYTONPASSFILE=/tmp/.adminpwd gnuhealth /srv/gnuhealth/gnuhealth/tryton/server/trytond-4.2.10/bin/trytond-admin -d gnuhealth --all -v
rm -f /tmp/.adminpwd
+spotter-appmgr update-login gnuhealth "${GNUHEALTH_ADMIN_USER}" "${GNUHEALTH_ADMIN_PWD}"
# Populate demo database
wget http://health.gnu.org/downloads/postgres_dumps/gnuhealth-32-demo.sql.gz -O /tmp/gnuhealth_demo.sql.gz
zcat /tmp/gnuhealth_demo.sql.gz | docker exec -i -e PGPASSWORD=${GNUHEALTH_PWD} postgres psql gnuhealth_demo gnuhealth
rm -f /tmp/gnuhealth_demo.sql.gz
-
-# Create GNU Health service
-cp ${SOURCE_DIR}/etc/init.d/gnuhealth /etc/init.d/gnuhealth
-rc-update add gnuhealth
-service gnuhealth start
-
-# Add application definition
-spotter-appmgr add-app gnuhealth "https://gnuhealth.{host}/index.html" admin "${GNUHEALTH_ADMIN_PWD}"
-spotter-appmgr add-app gnuhealth-clients -p clienturl "gnuhealth.{host}"
diff --git a/gnuhealth/etc/init.d/gnuhealth b/gnuhealth/etc/init.d/gnuhealth
index 5c1f59c..bc1c9ee 100755
--- a/gnuhealth/etc/init.d/gnuhealth
+++ b/gnuhealth/etc/init.d/gnuhealth
@@ -3,8 +3,7 @@
description="GNU Health docker container"
depend() {
- need docker net postgres
- use dns logger netmount postfix
+ need docker postgres
}
start() {
@@ -18,7 +17,11 @@ start() {
}
start_post() {
- /usr/local/bin/spotter-appmgr update-proxy gnuhealth
+ /usr/bin/spotter-appmgr register-proxy gnuhealth
+}
+
+stop_pre() {
+ /usr/bin/spotter-appmgr unregister-proxy gnuhealth
}
stop() {
diff --git a/kanboard.sh b/kanboard.sh
index 18437fb..3530738 100755
--- a/kanboard.sh
+++ b/kanboard.sh
@@ -5,9 +5,12 @@ SOURCE_DIR=$(realpath $(dirname "${0}"))/kanboard
# Check prerequisites
docker image ls | grep -q postfix || $(realpath $(dirname "${0}"))/postfix.sh
docker image ls | grep -q postgres || $(realpath $(dirname "${0}"))/postgres.sh
+service postgres start
# Build Docker container
docker build -t kanboard ${SOURCE_DIR}
+cp ${SOURCE_DIR}/etc/init.d/kanboard /etc/init.d/kanboard
+rc-update -u
# Populate database
export KANBOARD_PWD=$(head -c 18 /dev/urandom | base64)
@@ -22,15 +25,7 @@ export KANBOARD_ADMIN_USER=admin
export KANBOARD_ADMIN_PWD=$(head -c 12 /dev/urandom | base64)
export KANBOARD_ADMIN_HASH=$(docker run --rm kanboard php -r "echo password_hash('${KANBOARD_ADMIN_PWD}', PASSWORD_BCRYPT);")
envsubst <${SOURCE_DIR}/adminpwd.sql | docker exec -i postgres psql kanboard
-
-# Create KanBoard service
-cp ${SOURCE_DIR}/etc/init.d/kanboard /etc/init.d/kanboard
-rc-update add kanboard
-service kanboard start
+spotter-appmgr update-login kanboard "${KANBOARD_ADMIN_USER}" "${KANBOARD_ADMIN_PWD}"
# Install cron job
cp ${SOURCE_DIR}/etc/periodic/daily/kanboard /etc/periodic/daily/kanboard
-
-# Add application definition
-spotter-appmgr add-app kanboard "https://kanboard.{host}/" "${KANBOARD_ADMIN_USER}" "${KANBOARD_ADMIN_PWD}"
-spotter-appmgr add-app kanboard-mobile -p clienturl "https://kanboard.{host}"
diff --git a/kanboard/etc/init.d/kanboard b/kanboard/etc/init.d/kanboard
index d959c4f..0d13268 100755
--- a/kanboard/etc/init.d/kanboard
+++ b/kanboard/etc/init.d/kanboard
@@ -3,8 +3,7 @@
description="KanBoard docker container"
depend() {
- need docker net postgres
- use dns logger netmount postfix
+ need docker postfix postgres
}
start() {
@@ -19,7 +18,11 @@ start() {
}
start_post() {
- /usr/local/bin/spotter-appmgr update-proxy kanboard
+ /usr/bin/spotter-appmgr register-proxy kanboard
+}
+
+stop_pre() {
+ /usr/bin/spotter-appmgr unregister-proxy kanboard
}
stop() {
diff --git a/mariadb.sh b/mariadb.sh
index 9e46bce..0f852a2 100755
--- a/mariadb.sh
+++ b/mariadb.sh
@@ -4,6 +4,8 @@ SOURCE_DIR=$(realpath $(dirname "${0}"))/mariadb
# Build Docker container
docker build -t mariadb ${SOURCE_DIR}
+cp ${SOURCE_DIR}/etc/init.d/mariadb /etc/init.d/mariadb
+rc-update -u
# Create MariaDB instance
mkdir -p /srv/mariadb/conf /srv/mariadb/data
@@ -18,11 +20,6 @@ if [ ${DEBUG:-0} -eq 1 ]; then
sed -i 's/#general_log/general_log/g' /srv/mariadb/conf/my.cnf
fi
-# Configure MariaDB service
-cp ${SOURCE_DIR}/etc/init.d/mariadb /etc/init.d/mariadb
-rc-update add mariadb
-service mariadb start
-
# Configure MariaDB admin
-docker exec -i mariadb sh -c 'until [ -x /run/mysqld/mysqld.sock ]; do usleep 100000; done'
+service mariadb start
cat ${SOURCE_DIR}/adminpwd.sql | docker exec -i mariadb mysql
diff --git a/mariadb/etc/init.d/mariadb b/mariadb/etc/init.d/mariadb
index d02bf09..f3d58d9 100755
--- a/mariadb/etc/init.d/mariadb
+++ b/mariadb/etc/init.d/mariadb
@@ -3,8 +3,7 @@
description="MariaDB docker container"
depend() {
- need docker net
- use dns logger netmount
+ need docker
}
start() {
@@ -16,6 +15,10 @@ start() {
mariadb
}
+start_post() {
+ timeout -t 3 docker exec mariadb sh -c 'until [ -e /run/mysqld/mysqld.sock ]; do usleep 50000; done'
+}
+
stop() {
/usr/bin/docker stop mariadb
}
diff --git a/mifosx.sh b/mifosx.sh
index ff4a33c..1e14810 100755
--- a/mifosx.sh
+++ b/mifosx.sh
@@ -6,9 +6,12 @@ SOURCE_DIR=$(realpath $(dirname "${0}"))/mifosx
docker image ls | grep -q mariadb || $(realpath $(dirname "${0}"))/mariadb.sh
docker image ls | grep -q postfix || $(realpath $(dirname "${0}"))/postfix.sh
docker image ls | grep -q tomcat || $(realpath $(dirname "${0}"))/tomcat.sh
+service mariadb start
# Build Docker container
docker build -t mifosx ${SOURCE_DIR}
+cp ${SOURCE_DIR}/etc/init.d/mifosx /etc/init.d/mifosx
+rc-update -u
# Create databases
export MIFOSX_PWD=$(head -c 18 /dev/urandom | base64)
@@ -24,22 +27,17 @@ envsubst <${SOURCE_DIR}/srv/mifosx/conf/context.xml >/srv/mifosx/conf/context.xm
cp ${SOURCE_DIR}/srv/mifosx/conf/server.xml /srv/mifosx/conf/server.xml
cp ${SOURCE_DIR}/srv/mifosx/update-url.sh /srv/mifosx/update-url.sh
-# Create Mifos X service
-cp ${SOURCE_DIR}/etc/init.d/mifosx /etc/init.d/mifosx
-rc-update add mifosx
+# Populate database
service mifosx start
-
-# Update admin account
echo `date` '- Waiting for database to be populated. This should take about a minute.'
until docker logs mifosx 2>&1 | grep -q 'Migrating schema `mifostenant-default` to version 5000'; do
sleep 1
done
+
+# Update admin account
export MIFOSX_ADMIN_USER=admin
export MIFOSX_ADMIN_EMAIL=admin@example.com
export MIFOSX_ADMIN_PWD=$(head -c 12 /dev/urandom | base64 | tr -d "+")
export MIFOSX_ADMIN_HASH=$(echo -n "${MIFOSX_ADMIN_PWD}{1}" | sha256sum | awk '{print $1}')
envsubst <${SOURCE_DIR}/adminpwd.sql | docker exec -i mariadb mysql mifostenant-default
-
-# Add application definition
-spotter-appmgr add-app mifosx "https://mifosx.{host}/community-app/" "${MIFOSX_ADMIN_USER}" "${MIFOSX_ADMIN_PWD}"
-spotter-appmgr add-app mifosx-mobile -p clienturl "mifosx.{host}"
+spotter-appmgr update-login mifosx "${MIFOSX_ADMIN_USER}" "${MIFOSX_ADMIN_PWD}"
diff --git a/mifosx/etc/init.d/mifosx b/mifosx/etc/init.d/mifosx
index 58da091..1a7252b 100755
--- a/mifosx/etc/init.d/mifosx
+++ b/mifosx/etc/init.d/mifosx
@@ -3,8 +3,7 @@
description="Mifos X docker container"
depend() {
- need docker net mariadb
- use dns logger netmount postfix
+ need docker mariadb postfix
}
start() {
@@ -19,7 +18,11 @@ start() {
}
start_post() {
- /usr/local/bin/spotter-appmgr update-proxy mifosx
+ /usr/bin/spotter-appmgr register-proxy mifosx
+}
+
+stop_pre() {
+ /usr/bin/spotter-appmgr unregister-proxy mifosx
}
stop() {
diff --git a/mifosx/srv/mifosx/conf/server.xml b/mifosx/srv/mifosx/conf/server.xml
index 2d8e62a..33e851e 100644
--- a/mifosx/srv/mifosx/conf/server.xml
+++ b/mifosx/srv/mifosx/conf/server.xml
@@ -68,7 +68,7 @@
-->