diff --git a/.gitignore b/.gitignore index a4c24ac..32b9048 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /node_modules/ .DS_Store -/typings/ \ No newline at end of file +/typings/ +/results/ +/service-plans/*/results/ \ No newline at end of file diff --git a/README.md b/README.md index b68990d..a20f4af 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,65 @@ -Emergence -========= +# Emergence [![Join the chat at https://gitter.im/JarvusInnovations/Emergence](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/JarvusInnovations/Emergence?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Emergence is a NodeJS-powered server that provides a web interface for configuring and launching the services that power your website or application. It provides virtualized storage containers for your code and assets that are accessible via WebDAV and API. Each storage container maintains complete version history for all files and can be linked over the web to a parent container that files will be inherited from just-in-time. -Features ---------- -* Rich web interface provides for all setup and management -* Plugin-based support for system services to be configured and run - * Plugins included for nginx and mysql -* Versioned storage containers - * Inherit remote containers over http - * Copy-on-write - * Accessible remotely via WebDAV and locally via API -* PHP development framework - * Classes automatically loaded from storage container - * Lightweight MVC classes optimized for serial inheritance across sites - * Extendable templating system powered by Dwoo - - -Requirements -------------- -* NodeJS -* npm - * underscore - * node-static -* mysql -* nginx -* php-fpm - * php 5.3+ - * apc - * mysqli - - -Installation --------------- +## Features + +- Rich web interface provides for all setup and management +- Plugin-based support for system services to be configured and run + - Plugins included for nginx and mysql +- Versioned storage containers + - Inherit remote containers over http + - Copy-on-write + - Accessible remotely via WebDAV and locally via API +- PHP development framework + - Classes automatically loaded from storage container + - Lightweight MVC classes optimized for serial inheritance across sites + - Extendable templating system powered by Dwoo + + +## Installation + See http://emr.ge/docs +## Building with Habitat + +- `cd ~/Repositories/emergence` +- `hab studio enter` +- `build` +- Optionally export a docker container image: `hab pkg export docker emergence/emergence-kernel` + + +## Debugging with Habitat + +From within studio: `hab sup start emergence/emergence-kernel` + + +## Running with Docker + +- Start a container from new image: `docker run -it -p 9080:80 -p 9083:9083 --name myemergence emergence/emergence-kernel` + + +## Habitat Migration Todo + +- [X] Use habitat config system to generate base service configs, add `include .../var/nginx.sites` to nginx, stick dynamic ish there +- [ ] Compare stock services configs with hab-provided configs +- [ ] Pull Request mariadb fix +- [ ] Get nginx running with configured external config +- [X] Move stock nginx config bodies to .include files (e.g. http.include) +- [X] Add default static nginx site to nginx.conf before sites include +- [ ] Review all initialized permissions +- [ ] Remove shelljs +- [ ] Upgrade dwoo and see if php7 works + +- Get docker container working + - [X] Run new docker container + - [X] Check that Zend is loaded now + - [X] get shell wrapper working + - [X] Figure out why cookies dont work -- set from console for now + - [X] Commit changes -Visit http://serverhost:9083 in your browser +- [ ] PR readline into core-plans php and php5 diff --git a/bin/create-site.sh b/bin/create-site similarity index 84% rename from bin/create-site.sh rename to bin/create-site index 0a098e6..d2167e3 100755 --- a/bin/create-site.sh +++ b/bin/create-site @@ -1,5 +1,21 @@ #!/bin/bash + +# determine location of this script +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + + +# get path to underscore +UNDERSCORE=$DIR/../node_modules/.bin/underscore + + +# parse args DEFAULT_PRECACHE_TREES='dwoo-plugins,event-handlers,html-templates,php-classes,php-config,php-migrations,site-root,site-tasks' DEFAULT_GENERATE_TABLES='UserSession,User' @@ -77,12 +93,8 @@ case $i in esac done -if [ "$GENERATE_TABLES" ] || [ "$PRECACHE_TREES" ] || [ "$ENTER_SHELL" ]; then - command -v underscore >/dev/null 2>&1 || { echo >&2 "underscore must be installed to use --precache-trees or --generate-tables"; exit 1; } -fi - if [ -z "$KERNEL_SOCKET" ]; then - KERNEL_SOCKET="/emergence/kernel.sock" + KERNEL_SOCKET="/hab/svc/emergence-kernel/var/run/kernel.sock" fi if [ ! -S "$KERNEL_SOCKET" ]; then @@ -136,7 +148,7 @@ RESPONSE=$( --unix-socket "${KERNEL_SOCKET}" \ -H "Content-Type: application/json" \ -d "${REQUEST_BODY}" \ - "http:/sites" + "http://localhost/sites" ) echo "$RESPONSE" @@ -145,7 +157,7 @@ if [ -z "$PRECACHE_TREES" ] && [ -z "$GENERATE_TABLES" ] && [ -z "$ENTER_SHELL" exit 0 fi -SITE_HANDLE=$(echo "${RESPONSE}" | underscore --outfmt=text extract data.handle) +SITE_HANDLE=$(echo "${RESPONSE}" | $UNDERSCORE --outfmt=text extract data.handle) if [ "$PRECACHE_TREES" ]; then emergence-shell $SITE_HANDLE 1>&2 << END_OF_PHP diff --git a/bin/git-shell b/bin/git-shell index c508f57..dfb7731 100755 --- a/bin/git-shell +++ b/bin/git-shell @@ -21,7 +21,6 @@ SITE_HANDLE=$1 SITE_LAYER=$2 UNDERSCORE=$DIR/../node_modules/.bin/underscore -EMERGENCE_USER=`cat /emergence/config.json | $UNDERSCORE extract user --outfmt text` BLACK="\033[01;30m" MAGENTA="\033[1;31m" @@ -43,13 +42,12 @@ PS2="\[$ORANGE\]→ \[$RESET\]" \ # check environment -test $EUID -eq 0 || die "emergence-git-shell must be run with sudo" test -x "$UNDERSCORE" || die "unable to execute $UNDERSCORE" test -n "$SITE_HANDLE" -a -n "$SITE_LAYER"|| die "usage: emergence-git-shell site_handle layer_id" # get site directory -SITE_DIR="/emergence/sites/$SITE_HANDLE" +SITE_DIR="/hab/svc/emergence-kernel/data/sites/$SITE_HANDLE" test -d "$SITE_DIR" || die "site $SITE_HANDLE not found at $SITE_DIR" @@ -89,6 +87,20 @@ if [ -n "$GIT_USER_DIRTY" ]; then fi +# setup environment +export PS1 +export PS2 +export SITE_HOSTNAME +export SITE_LAYER +export GIT_SSH + +export HISTFILE="$GIT_DIR.bash_history" +export GIT_AUTHOR_NAME="$GIT_NAME" +export GIT_AUTHOR_EMAIL="$GIT_EMAIL" +export GIT_COMMITTER_NAME="$GIT_NAME" +export GIT_COMMITTER_EMAIL="$GIT_EMAIL" + + # execute subshell echo "Opening git shell at $GIT_DIR" cd $GIT_DIR @@ -97,16 +109,8 @@ git status echo "Committing as $GIT_NAME <$GIT_EMAIL>" -exec sudo -u $EMERGENCE_USER \ - HOME="$GIT_DIR" \ - HISTFILE="$GIT_DIR.bash_history" \ - GIT_SSH="$GIT_SSH" \ - GIT_AUTHOR_NAME="$GIT_NAME" \ - GIT_AUTHOR_EMAIL="$GIT_EMAIL" \ - GIT_COMMITTER_NAME="$GIT_NAME" \ - GIT_COMMITTER_EMAIL="$GIT_EMAIL" \ - PS1="$PS1" \ - PS2="$PS2" \ - SITE_HOSTNAME="$SITE_HOSTNAME" \ - SITE_LAYER="$SITE_LAYER" \ - /bin/bash --norc \ No newline at end of file +if [ "$(whoami)" == "hab" ]; then + HOME="$GIT_DIR" exec bash --norc +else + exec su hab -c "HOME='$GIT_DIR' bash --norc" +fi \ No newline at end of file diff --git a/bin/kernel b/bin/kernel index d231123..47eeacd 100755 --- a/bin/kernel +++ b/bin/kernel @@ -6,160 +6,19 @@ var _ = require('underscore'), url = require('url'), path = require('path'), fs = require('fs'), - sitesLib = require('../kernel-lib/sites.js'); - - -var CONFIG; - -if (fs.existsSync('/emergence/config.json')) { - // try to load existing kernel config - - CONFIG = JSON.parse(fs.readFileSync('/emergence/config.json', 'ascii')); -} else { - // try to smart-init a new kernel config - var issueFile = "", - platform = require('os').platform(), - distro = platform; - - // detect ubuntu - // TODO: find better ways to determine default options than platform detection - if (platform == 'linux') { - try { - issueFile = fs.readFileSync('/etc/issue', 'ascii'); - if (issueFile.match(/Ubuntu/)) { - distro = 'ubuntu'; - } - } catch (err) { - // ignore any failure to real /etc/issue and leave platform set to linux - } - } - - console.log('Initializing new emergence environment for distro="'+distro+'"...'); - - if (!fs.existsSync('/emergence')) { - fs.mkdirSync('/emergence', '775'); - } - - CONFIG = { - user: distro=='ubuntu' ? 'www-data' : 'nobody', - group: distro=='ubuntu' ? 'www-data' : 'nobody', - - server: { - host: "0.0.0.0" - }, - services: { - plugins: { } - } - }; - - - - - // detect nginx - if (fs.existsSync('/usr/sbin/nginx')) { - CONFIG.services.plugins.web = { - type: 'nginx', - autoStart: true, - execPath: '/usr/sbin/nginx', - bindHost: '0.0.0.0' - }; - } else if (fs.existsSync('/usr/local/sbin/nginx')) { - CONFIG.services.plugins.web = { - type: 'nginx', - autoStart: true, - execPath: '/usr/local/sbin/nginx', - bindHost: '0.0.0.0' - }; - } - - // detect mysql - if (fs.existsSync('/usr/sbin/mysqld')) { - CONFIG.services.plugins.sql = { - type: 'mysql', - autoStart: true, - execPath: '/usr/sbin/mysqld', - managerUser: 'root', - managerPassword: sitesLib.generatePassword() - }; - } else if (fs.existsSync('/usr/local/bin/mysqld')) { - CONFIG.services.plugins.sql = { - type: 'mysql', - autoStart: true, - execPath: '/usr/local/bin/mysqld', - managerUser: 'root', - managerPassword: sitesLib.generatePassword() - }; - } else if (fs.existsSync('/usr/bin/mysqld_safe')) { - CONFIG.services.plugins.sql = { - type: 'mysql', - autoStart: true, - execPath: '/usr/bin/mysqld_safe', - managerUser: 'root', - managerPassword: sitesLib.generatePassword() - }; - } - - // detect php-fpm - if (fs.existsSync('/usr/sbin/php-fpm5.6')) { - CONFIG.services.plugins.php = { - type: 'php-fpm', - autoStart: true, - execPath: '/usr/sbin/php-fpm5.6' - }; - } else if (fs.existsSync('/usr/sbin/php-fpm7.0')) { - CONFIG.services.plugins.php = { - type: 'php-fpm', - autoStart: true, - execPath: '/usr/sbin/php-fpm7.0' - }; - } else if (fs.existsSync('/usr/bin/php-fpm')) { - CONFIG.services.plugins.php = { - type: 'php-fpm', - autoStart: true, - execPath: '/usr/bin/php-fpm' - }; - } else if (fs.existsSync('/usr/sbin/php5-fpm')) { - CONFIG.services.plugins.php = { - type: 'php-fpm', - autoStart: true, - execPath: '/usr/sbin/php5-fpm' - }; - } else if (fs.existsSync('/usr/local/sbin/php-fpm')) { - CONFIG.services.plugins.php = { - type: 'php-fpm', - autoStart: true, - execPath: '/usr/local/sbin/php-fpm' - }; - } else if (fs.existsSync('/usr/sbin/php-fpm')) { - CONFIG.services.plugins.php = { - type: 'php-fpm', - autoStart: true, - execPath: '/usr/sbin/php-fpm' - }; - } - - fs.writeFileSync('/emergence/config.json', JSON.stringify(CONFIG, null, 4)); - fs.chmodSync('/emergence/config.json', '600'); - console.log('Generated and wrote initial config: /emergence/config.json'); -} - -// create default admin user -if (!fs.existsSync('/emergence/admins.htpasswd')) { - console.log('Creating default administrative user: admin/admin'); - fs.writeFileSync('/emergence/admins.htpasswd', 'admin:{SHA}0DPiKuNIrrVmD8IUCuw1hQxNqZc='); - fs.chmodSync('/emergence/admins.htpasswd', '600'); -} + sitesLib = require('../kernel-lib/sites.js'), + kernelConfig = require('/hab/svc/emergence-kernel/config/config.json'); // load core modules -var eSites = sitesLib.createSites(CONFIG); -var eServices = require('../kernel-lib/services.js').createServices(eSites, CONFIG); +var eSites = sitesLib.createSites(kernelConfig); +var eServices = require('../kernel-lib/services.js').createServices(eSites, kernelConfig); // instantiate management server var eManagementServer = require('../kernel-lib/server.js').createServer({ sites: eSites, services: eServices -}, CONFIG); +}, kernelConfig); // start server diff --git a/bin/shell b/bin/shell index 5f00f6e..d1787c3 100755 --- a/bin/shell +++ b/bin/shell @@ -20,7 +20,7 @@ DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" [ -n "$1" ] || die "Usage: emergence-kernel site-handle" siteHandle=$1 -siteDir="/emergence/sites/$siteHandle" +siteDir="/hab/svc/emergence-kernel/data/sites/$siteHandle" [ -d "$siteDir" ] || die "Site '$siteHandle' not found at '$siteDir'" @@ -29,12 +29,14 @@ siteDir="/emergence/sites/$siteHandle" autoPrependScript=$(mktemp); echo " $autoPrependScript +echo "\$serverConfig = json_decode(file_get_contents('/hab/svc/emergence-kernel/config/config.json'), true);" >> $autoPrependScript +echo "date_default_timezone_set(\$serverConfig['services']['php']['timezone']);" >> $autoPrependScript echo "require('`dirname $DIR`/php-bootstrap/bootstrap.inc.php');" >> $autoPrependScript echo "Site::initialize('$siteDir');" >> $autoPrependScript -# give www-data access to script -chgrp www-data $autoPrependScript +# give hab access to script +chgrp hab $autoPrependScript chmod g+r $autoPrependScript @@ -55,7 +57,13 @@ fi # execute interactive shell -TERM=$TERM sudo -E -u www-data -g www-data php -d auto_prepend_file=$autoPrependScript -d apc.enable_cli=on $INPUT_ARGS +PHP_ARGS="-d auto_prepend_file=$autoPrependScript -d apc.enable_cli=on $INPUT_ARGS" + +if [ "$(whoami)" == "hab" ]; then + TERM=$TERM php $PHP_ARGS +else + TERM=$TERM su hab -c "php $PHP_ARGS" +fi # clean up diff --git a/bin/su b/bin/su index b44cb1e..2fbf742 100755 --- a/bin/su +++ b/bin/su @@ -1,2 +1,2 @@ #!/bin/bash -sudo su -l www-data -p \ No newline at end of file +sudo su -l hab -p \ No newline at end of file diff --git a/clean-runtime.sh b/clean-runtime.sh new file mode 100755 index 0000000..645ffb5 --- /dev/null +++ b/clean-runtime.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +hab sup term +hab pkg exec core/busybox-static killall php-fpm +hab pkg exec core/busybox-static killall nginx +hab pkg exec core/busybox-static killall mysqld +rm /hab/svc/emergence-kernel/var/run/kernel.sock +find /hab/svc/emergence-kernel/var/run/ -type f -delete \ No newline at end of file diff --git a/debug.toml b/debug.toml new file mode 100644 index 0000000..486049c --- /dev/null +++ b/debug.toml @@ -0,0 +1,2 @@ +[php] +stat_scripts=true diff --git a/default-site/index.html b/default-site/index.html new file mode 100644 index 0000000..1b25d78 --- /dev/null +++ b/default-site/index.html @@ -0,0 +1,9 @@ + + + emergence + + +

Welcome to emergence!

+

No site is configure (yet) at this address. If you are the webmaster, visit the emergence control panel and create a site

+ + \ No newline at end of file diff --git a/habitat/config/config.json b/habitat/config/config.json new file mode 100644 index 0000000..f165af2 --- /dev/null +++ b/habitat/config/config.json @@ -0,0 +1,24 @@ +{ + "user": "{{pkg.svc_user}}", + "group": "{{pkg.svc_group}}", + "server": { + "host": "{{cfg.kernel.host}}" + }, + "services": { + "web": { + "type": "nginx", + "packagePath": "{{pkgPathFor "emergence/nginx"}}", + "bindHost": "{{cfg.web.host}}", + "bindPort": "{{cfg.web.port}}" + }, + "sql": { + "type": "mariadb", + "packagePath": "{{pkgPathFor "emergence/mariadb"}}" + }, + "php": { + "type": "php-fpm", + "packagePath": "{{pkgPathFor "emergence/php5"}}", + "timezone": "{{cfg.php.timezone}}" + } + } +} \ No newline at end of file diff --git a/habitat/config/mariadb b/habitat/config/mariadb new file mode 100644 index 0000000..30ff15f --- /dev/null +++ b/habitat/config/mariadb @@ -0,0 +1,37 @@ +[mysqld] +character-set-server = utf8 +user = hab +port = 3306 +socket = {{pkg.svc_var_path}}/run/mariadb.sock +pid-file = {{pkg.svc_var_path}}/run/mariadb.pid +datadir = {{pkg.svc_data_path}}/services/mariadb +basedir = {{pkgPathFor "emergence/mariadb"}} +skip-external-locking +key_buffer_size = 16M +max_allowed_packet = 1M +sort_buffer_size = 512K +net_buffer_length = 8K +read_buffer_size = 256K +read_rnd_buffer_size = 512K +myisam_sort_buffer_size = 8M +log-bin = mysqld-bin +expire_logs_days = 2 +server-id = 1 +tmpdir = /tmp/ +innodb_buffer_pool_size = 16M +innodb_data_file_path = ibdata1:10M:autoextend:max:128M +innodb_log_file_size = 5M +innodb_log_buffer_size = 8M +innodb_log_files_in_group = 2 +innodb_flush_log_at_trx_commit = 1 +innodb_lock_wait_timeout = 50 +innodb_file_per_table +max_binlog_size = 100M +binlog_format = row +table_open_cache = 64 + +{{#if cfg.sql.host~}} + bind-address = {{cfg.sql.host}} +{{~else~}} + skip-networking +{{~/if}} diff --git a/habitat/config/nginx b/habitat/config/nginx new file mode 100644 index 0000000..7ae3810 --- /dev/null +++ b/habitat/config/nginx @@ -0,0 +1,68 @@ +user hab hab; + +worker_processes auto; +events { + worker_connections 1024; + use epoll; +} + +pid {{pkg.svc_var_path}}/run/nginx.pid; +lock_file {{pkg.svc_var_path}}/run/nginx.lock; +error_log {{pkg.svc_var_path}}/log/nginx.err info; + +http { + client_body_temp_path {{pkg.svc_var_path}}/tmp/nginx/client-body; + proxy_temp_path {{pkg.svc_var_path}}/tmp/nginx/proxy; + fastcgi_temp_path {{pkg.svc_var_path}}/tmp/nginx/fastcgi; + scgi_temp_path {{pkg.svc_var_path}}/tmp/nginx/scgi; + uwsgi_temp_path {{pkg.svc_var_path}}/tmp/nginx/uwsgi; + + include {{pkgPathFor "emergence/nginx"}}/config/mime.types; + default_type application/octet-stream; + + log_format main + '$host $remote_addr - $remote_user [$time_local] ' + '"$request" $status $bytes_sent ' + '"$http_referer" "$http_user_agent" ' + '"$gzip_ratio"'; + + client_header_timeout 10m; + client_body_timeout 10m; + send_timeout 10m; + connection_pool_size 256; + client_max_body_size 200m; + client_body_buffer_size 128k; + client_header_buffer_size 1k; + large_client_header_buffers 8 512k; + request_pool_size 4k; + server_names_hash_bucket_size 1024; + types_hash_max_size 2048; + gzip on; + gzip_min_length 1100; + gzip_buffers 4 8k; + gzip_types text/plain text/css text/x-scss text/x-html-template text/x-component text/xml application/xml application/javascript application/json application/php application/atom+xml application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/xhtml+xml font/opentype image/svg+xml image/x-icon; + output_buffers 1 32k; + postpone_output 1460; + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 75 20; + ignore_invalid_headers on; + fastcgi_read_timeout 6h; + fastcgi_buffers 32 64k; + server_tokens off; + + server { + listen {{cfg.web.host}}:{{cfg.web.port}}; + server_name localhost; + access_log off; + + location / { + root {{pkg.path}}/app/default-site; + index index.html; + error_page 404 index.html; + } + } + + include {{pkg.svc_var_path}}/config/nginx.sites; +} \ No newline at end of file diff --git a/habitat/config/php-fpm b/habitat/config/php-fpm new file mode 100644 index 0000000..40c3439 --- /dev/null +++ b/habitat/config/php-fpm @@ -0,0 +1,23 @@ +[global] +pid = {{pkg.svc_var_path}}/run/php-fpm.pid +error_log = {{pkg.svc_var_path}}/log/php-fpm.err + + +[www] +user = hab +group = hab +catch_workers_output = on + +listen = {{pkg.svc_var_path}}/run/php-fpm.sock +listen.owner = {{pkg.svc_user}} +listen.group = {{pkg.svc_group}} + +pm = dynamic +pm.max_children = {{cfg.php.max_children}} +pm.start_servers = {{cfg.php.start_servers}} +pm.min_spare_servers = {{cfg.php.min_spare_servers}} +pm.max_spare_servers = {{cfg.php.max_spare_servers}} + +{{~#if cfg.php.status_path}} +pm.status_path = {{cfg.php.status_path}} +{{~/if}} \ No newline at end of file diff --git a/habitat/config/php.ini b/habitat/config/php.ini new file mode 100644 index 0000000..e2d6706 --- /dev/null +++ b/habitat/config/php.ini @@ -0,0 +1,17 @@ +[PHP] +short_open_tag = on + +upload_max_filesize = {{cfg.php.upload_max_filesize}} +post_max_size = {{cfg.php.post_max_size}} +memory_limit = {{cfg.php.memory_limit}} +error_reporting = {{cfg.php.error_reporting}} +date.timezone = {{cfg.php.timezone}} + +apc.shm_size = {{cfg.php.shm_size}} +apc.shm_segments = 1 +apc.slam_defense = 0 +apc.stat = {{#if cfg.php.stat_scripts}}1{{else}}0{{/if}} + +zend_extension = opcache.so +opcache.enable = on +opcache.validate_timestamps = {{#if cfg.php.stat_scripts}}1{{else}}0{{/if}} \ No newline at end of file diff --git a/habitat/default.toml b/habitat/default.toml new file mode 100644 index 0000000..6cc0d34 --- /dev/null +++ b/habitat/default.toml @@ -0,0 +1,29 @@ +# Use this file to templatize your application's native configuration files. +# See the docs at https://www.habitat.sh/docs/create-packages-configure/. +# You can safely delete this file if you don't need it. + +[kernel] +host="0.0.0.0" + +[web] +host="0.0.0.0" +port=80 + +[sql] +host="127.0.0.1" + +[php] +stat_scripts=false +status_path=false +error_reporting="E_ALL & ~E_NOTICE" +timezone="America/New_York" + +max_children=50 +start_servers=5 +min_spare_servers=5 +max_spare_servers=10 + +upload_max_filesize="200M" +post_max_size="200M" +memory_limit="200M" +shm_size="512M" \ No newline at end of file diff --git a/habitat/hooks/init b/habitat/hooks/init new file mode 100755 index 0000000..032f8d4 --- /dev/null +++ b/habitat/hooks/init @@ -0,0 +1,48 @@ +#!/bin/bash + +# initialize users database +AUTHFILE="{{pkg.svc_data_path}}/users.htpasswd" + +if [ ! -f "$AUTHFILE" ]; then + echo "Initializing $AUTHFILE with admin/admin user" + echo "admin:{SHA}0DPiKuNIrrVmD8IUCuw1hQxNqZc=" > "$AUTHFILE" + chown root:hab "$AUTHFILE" + chmod 640 "$AUTHFILE" +fi + +# fix permissions on config directory +chmod g+rX -R "{{pkg.svc_config_path}}" + +# initialize var directories +cd "{{pkg.svc_var_path}}" +chmod g+rX -R . +for DIR in log run config tmp tmp/nginx; do + if [ ! -d "$DIR" ]; then + mkdir "$DIR" + chmod 770 "$DIR" + chown root:hab "$DIR" + fi +done + +# initialize data directories +cd "{{pkg.svc_data_path}}" +chmod g+rX -R . +for DIR in sites services; do + if [ ! -d "$DIR" ]; then + mkdir "$DIR" + chmod 770 "$DIR" + chown root:hab "$DIR" + fi +done + +# initialize static asset links +cd "{{pkg.svc_static_path}}" +chmod g+rX -R . +ln -sf "{{pkg.path}}/app/php-bootstrap" +ln -sf "{{pkg.path}}/app/kernel-www" + +# initialize bin links +hab pkg binlink core/hab hab +hab pkg binlink core/git git +hab pkg binlink core/openssh ssh-keygen +hab pkg binlink core/openssh ssh \ No newline at end of file diff --git a/habitat/plan.sh b/habitat/plan.sh new file mode 100644 index 0000000..312bc9d --- /dev/null +++ b/habitat/plan.sh @@ -0,0 +1,28 @@ +pkg_name=emergence-kernel +pkg_origin=emergence +pkg_version="1.0.0" +pkg_upstream_url="https://github.com/JarvusInnovations/emergence" +pkg_scaffolding=core/scaffolding-node +pkg_svc_user="root" + +pkg_build_deps=( + core/make + core/gcc + core/python2 +) + +pkg_deps=( + core/coreutils + core/bash + core/git + core/curl + core/openssh + emergence/nginx + emergence/mariadb + emergence/php5 +) + +do_install() { + do_default_install + fix_interpreter "$scaffolding_app_prefix/bin/*" core/bash bin/bash +} diff --git a/kernel-lib/server.js b/kernel-lib/server.js index 84dd2c7..64061a0 100644 --- a/kernel-lib/server.js +++ b/kernel-lib/server.js @@ -1,4 +1,5 @@ -var http = require('http'), +var net = require('net'), + http = require('http'), util = require('util'), fs = require('fs'), path = require('path'), @@ -15,56 +16,80 @@ exports.Server = function(paths, config) { // call events constructor events.EventEmitter.call(me); - // initialize options and apply defaults + // initialize configuration + me.socketPath = '/hab/svc/emergence-kernel/var/run/kernel.sock'; + me.staticDir = '/hab/svc/emergence-kernel/static/kernel-www'; + me.usersPath = '/hab/svc/emergence-kernel/data/users.htpasswd'; + me.paths = paths || {}; - me.options = options || {}; - me.options.host = me.options.host || '0.0.0.0'; - me.options.port = me.options.port || 9083; - me.options.sslKey = me.options.sslKey || null; - me.options.sslCert = me.options.sslCert || null; - me.options.staticDir = me.options.staticDir || path.resolve(__dirname, '../kernel-www'); - me.options.socketPath = 'socketPath' in me.options ? me.options.socketPath : '/emergence/kernel.sock'; - - // initialize state + me.host = options.host || '0.0.0.0'; + me.port = options.port || 9083; + me.defaultSuffix = options.defaultSuffix || null; + me.sslKey = options.sslKey || null; + me.sslCert = options.sslCert || null; }; util.inherits(exports.Server, events.EventEmitter); exports.Server.prototype.start = function() { - // create authenticator - this.httpAuth = require('http-auth')({ - authRealm: 'Emergence Node Management', - authFile: '/emergence/admins.htpasswd' + var me = this, + testConnection; + + // test if socket connection is already open + if (!me.socketPath || !fs.existsSync(me.socketPath)) { + _doStart(); + return; + } + + testConnection = net.createConnection(me.socketPath); + + testConnection.on('connect', function() { + testConnection.close(); + throw 'Socket file already exists and is live: '+me.socketPath; }); - // create static fileserver - this.fileServer = new static.Server(this.options.staticDir); + testConnection.on('error', function() { + console.log('Deleting stale socket file:', me.socketPath); + fs.unlinkSync(me.socketPath); + _doStart(); + }); - // listen on web port - if (this.options.sslKey && this.options.sslCert) { - this.webServer = require('https').createServer({ - key: fs.readFileSync(this.options.sslKey), - cert: fs.readFileSync(this.options.sslCert) - }, this.handleWebRequest.bind(this)).listen(this.options.port, this.options.host); + function _doStart() { + // create authenticator + me.httpAuth = require('http-auth')({ + authRealm: 'Emergence Node Management', + authFile: me.usersPath + }); - this.webProtocol = 'https'; - } else { - this.webServer = require('http').createServer(this.handleWebRequest.bind(this)).listen(this.options.port, this.options.host); + // create static fileserver + me.fileServer = new static.Server(me.staticDir); - this.webProtocol = 'http'; - } + // listen on web port + if (me.sslKey && me.sslCert) { + me.webServer = require('https').createServer({ + key: fs.readFileSync(me.sslKey), + cert: fs.readFileSync(me.sslCert) + }, me.handleWebRequest.bind(me)).listen(me.port, me.host); - // listen on unix socket - if (this.options.socketPath) { - this.socketServer = require('http').createServer(this.handleRequest.bind(this)).listen(this.options.socketPath); - fs.chmodSync(this.options.socketPath, '400'); - } + me.webProtocol = 'https'; + } else { + me.webServer = require('http').createServer(me.handleWebRequest.bind(me)).listen(me.port, me.host); + + me.webProtocol = 'http'; + } + + // listen on unix socket + if (me.socketPath) { + me.socketServer = require('http').createServer(me.handleRequest.bind(me)).listen(me.socketPath); + fs.chmodSync(me.socketPath, '400'); + } - // clean up on exit - process.on('exit', this.close.bind(this)); + // clean up on exit + process.on('exit', me.close.bind(me)); - console.log('Management server listening on '+this.webProtocol+'://'+this.options.host+':'+this.options.port); + console.log('Management server listening on '+me.webProtocol+'://'+me.host+':'+me.port); + } }; exports.createServer = function(paths, options) { @@ -96,7 +121,11 @@ exports.Server.prototype.handleRequest = function(request, response) { if (request.path[0] == 'server-config') { response.writeHead(200, {'Content-Type':'application/json'}); - response.end(JSON.stringify(me.options)); + response.end(JSON.stringify({ + host: me.host, + port: me.port, + defaultSuffix: me.defaultSuffix + })); return; } @@ -123,13 +152,15 @@ exports.Server.prototype.handleRequest = function(request, response) { }; exports.Server.prototype.close = function(options, error) { + var me = this; + console.log('Shutting down management server...'); - if (this.webServer) { - this.webServer.close(); + if (me.webServer) { + me.webServer.close(); } - if (this.socketServer) { - this.socketServer.close(); + if (me.socketServer) { + me.socketServer.close(); } }; \ No newline at end of file diff --git a/kernel-lib/services.js b/kernel-lib/services.js index 0853748..ce10cdf 100644 --- a/kernel-lib/services.js +++ b/kernel-lib/services.js @@ -5,49 +5,17 @@ var _ = require('underscore'), events = require('events'); exports.ServicesController = function(sites, config) { - var me = this, - options = config.services; + var me = this; me.sites = sites; + me.services = config.services; // call events constructor events.EventEmitter.call(me); - // initialize options and apply defaults - me.options = options || {}; - me.options.plugins = me.options.plugins || {}; - me.options.servicesDir = me.options.servicesDir || '/emergence/services'; - me.options.logsDir = me.options.logsDir || me.options.servicesDir+'/logs'; - me.options.configDir = me.options.configDir || me.options.servicesDir+'/etc'; - me.options.runDir = me.options.runDir || me.options.servicesDir+'/run'; - me.options.dataDir = me.options.dataDir || me.options.servicesDir+'/data'; - me.options.user = me.options.user || config.user; - me.options.group = me.options.group || config.group; - - // create required directories - if (!fs.existsSync(me.options.servicesDir)) { - fs.mkdirSync(me.options.servicesDir, '775'); - } - - if (!fs.existsSync(me.options.logsDir)) { - fs.mkdirSync(me.options.logsDir, '775'); - } - - if (!fs.existsSync(me.options.configDir)) { - fs.mkdirSync(me.options.configDir, '775'); - } - - if (!fs.existsSync(me.options.runDir)) { - fs.mkdirSync(me.options.runDir, '775'); - } - - if (!fs.existsSync(me.options.dataDir)) { - fs.mkdirSync(me.options.dataDir, '775'); - } - - // load service plugins + // load services me.services = {}; - _.each(me.options.plugins, function(plugin, name) { + _.each(config.services, function(plugin, name) { console.log('Loading service: '+name); if (_.isString(plugin)) { @@ -59,12 +27,10 @@ exports.ServicesController = function(sites, config) { me.services[name] = plugin; }); - // auto-start service plugins + // start services _.each(me.services, function(service, name) { - if (service.options.autoStart) { - console.log('Autostarting service: '+name); - service.start(); - } + console.log('Starting service: '+name); + service.start(); }); }; diff --git a/kernel-lib/services/mysql.js b/kernel-lib/services/mariadb.js similarity index 55% rename from kernel-lib/services/mysql.js rename to kernel-lib/services/mariadb.js index ae462e2..6990d8e 100644 --- a/kernel-lib/services/mysql.js +++ b/kernel-lib/services/mariadb.js @@ -19,55 +19,43 @@ exports.MysqlService = function(name, controller, options) { // call parent constructor exports.MysqlService.super_.apply(me, arguments); - // default options - me.options.configPath = me.options.configPath || controller.options.configDir + '/my.cnf'; - me.options.execPath = me.options.execPath || '/usr/sbin/mysqld'; - me.options.bindHost = me.options.bindHost || false; - me.options.runDir = me.options.runDir || controller.options.runDir + '/mysqld'; - me.options.pidPath = me.options.pidPath || me.options.runDir + '/mysqld.pid'; - me.options.socketPath = me.options.socketPath || me.options.runDir + '/mysqld.sock'; - me.options.dataDir = me.options.dataDir || controller.options.dataDir + '/mysql'; - me.options.logsDir = me.options.logsDir || controller.options.logsDir + '/mysql'; - me.options.errorLogPath = me.options.errorLogPath || me.options.logsDir + '/mysqld.err'; - me.options.managerUser = me.options.managerUser || 'emergence'; - me.options.managerPassword = me.options.managerPassword || ''; - - - // verify binary - if (!fs.existsSync(me.options.execPath)) { - throw 'execPath not found: ' + me.options.execPath; - } + // initialize configuration + me.packagePath = options.packagePath; + me.execPath = me.packagePath + '/bin/mysqld'; - // check binary version - console.log(me.name+': detecting mysqld version...'); - versionMatch = shell.exec(me.options.execPath+' --version').output.match(/mysqld\s+Ver\s+(\d+(\.\d+)*)(-MariaDB)?/); + me.configPath = '/hab/svc/emergence-kernel/config/mariadb'; + me.pidPath = '/hab/svc/emergence-kernel/var/run/mariadb.pid'; + me.socketPath = '/hab/svc/emergence-kernel/var/run/mariadb.sock'; + me.dataDir = '/hab/svc/emergence-kernel/data/services/mariadb'; + me.statePath = me.dataDir+'/state.json'; - if (!versionMatch) { - throw 'Failed to detect mysql version'; - } + me.execOptions = ['--defaults-file='+me.configPath, '--basedir='+me.packagePath]; - me.mysqldVersion = versionMatch[1]; - me.mysqldIsMaria = versionMatch[3] == '-MariaDB'; - console.log('%s: determined mysqld version: %s', me.name, me.mysqldVersion + (me.mysqldIsMaria ? ' (MariaDB)' : '')); + // load state + if (fs.existsSync(me.statePath)) { + me.state = JSON.parse(fs.readFileSync(me.statePath, 'ascii')); + } // check for existing mysqld process - if (fs.existsSync(me.options.pidPath)) { - me.pid = parseInt(fs.readFileSync(me.options.pidPath, 'ascii')); + if (fs.existsSync(me.pidPath)) { + me.pid = parseInt(fs.readFileSync(me.pidPath, 'ascii')); console.log(me.name+': found existing PID: '+me.pid+', checking /proc/'+me.pid); if (fs.existsSync('/proc/'+me.pid)) { me.status = 'online'; // instantiate MySQL client - me.client = new mariasql({ - unixSocket: me.options.socketPath, - user: me.options.managerUser, - password: me.options.managerPassword, - multiStatements: true - }); + if (me.state) { + me.client = new mariasql({ + unixSocket: me.socketPath, + user: 'root', + password: me.state.rootPassword, + multiStatements: true + }); + } } else { console.log(me.name+': process '+me.pid + ' not found, deleting .pid file'); - fs.unlinkSync(me.options.pidPath); + fs.unlinkSync(me.pidPath); } } @@ -87,55 +75,53 @@ exports.MysqlService.prototype.start = function(firstRun) { return false; } - // write configuration file - this.writeConfig(); + // init data directory if needed + if (!fs.existsSync(me.dataDir)) { + console.log('creating datadir as ', require("os").userInfo().username); + me.status = 'configuring'; - // init logs directory if needed - if (!fs.existsSync(me.options.logsDir)) { - console.log(me.name+': initializing new log directory'); - fs.mkdirSync(me.options.logsDir, '775'); - exec('chown -R mysql:mysql '+me.options.logsDir); - } + console.log(me.name+': initializing new data directory...'); + fs.mkdirSync(me.dataDir); + fs.chownSync(me.dataDir, me.controller.sites.dataUid, me.controller.sites.dataGid); + fs.chmodSync(me.dataDir, '750'); + // initialize state + me.state = { + rootPassword: me.controller.sites.generatePassword() + }; - // init run directory if needed - if (!fs.existsSync(me.options.runDir)) { - console.log(me.name+': initializing new run directory'); - fs.mkdirSync(me.options.runDir, '775'); - exec('chown -R mysql:mysql '+me.options.runDir); - } + fs.writeFileSync(me.statePath, JSON.stringify(me.state, null, 4)); + fs.chmodSync(me.statePath, '600'); - // init data directory if needed - if (!fs.existsSync(me.options.dataDir)) { - console.log(me.name+': initializing new data directory...'); - fs.mkdirSync(me.options.dataDir, '775'); - exec('chown -R mysql:mysql '+me.options.dataDir); + // use mysql_install_db to finish init + exec( + me.packagePath + '/scripts/mysql_install_db '+me.execOptions.join(' '), + function(error, stdout, stderr) { + if (error) { + console.log(me.name+': failed to initialize data directory', error); + return; + } - if (semver.lt(me.mysqldVersion, '5.7.6') || me.mysqldIsMaria) { - exec('mysql_install_db --defaults-file='+me.options.configPath, function(error, stdout, stderr) { me.start(true); - }); - } else { - exec('mysqld --initialize-insecure --user=mysql --datadir='+me.options.dataDir, function(error, stdout, stderr) { - me.start(true); - }); - } + } + ); - me.status = 'configuring'; return true; // not really started, we have to try again after mysql_install_db is done } // instantiate MySQL client - me.client = new mariasql({ - unixSocket: me.options.socketPath, - user: me.options.managerUser, - password: me.options.managerPassword, - multiStatements: true - }); + if (me.state) { + me.client = new mariasql({ + unixSocket: me.socketPath, + user: 'root', + password: me.state.rootPassword, + multiStatements: true + }); + } // spawn process - console.log(me.name+': spawning mysql: '+me.options.execPath); - me.proc = spawn(me.options.execPath, ['--defaults-file='+me.options.configPath, '--console'], {detached: true}); + console.log(me.name+': spawning mysql: '+me.execPath); + me.proc = spawn(me.execPath, me.execOptions.concat(['--console']), {detached: true}); me.pid = me.proc.pid; me.status = 'online'; @@ -208,7 +194,7 @@ exports.MysqlService.prototype.restart = function() { // wait for pid to disappear before attempting start process.stdout.write(me.name+': waiting for shutdown'); - while (fs.existsSync(me.options.pidPath)) { + while (fs.existsSync(me.pidPath)) { process.stdout.write('.'); now = new Date().getTime(); @@ -222,70 +208,6 @@ exports.MysqlService.prototype.restart = function() { return me.start(); }; -exports.MysqlService.prototype.writeConfig = function() { - fs.writeFileSync(this.options.configPath, this.makeConfig()); -}; - -exports.MysqlService.prototype.makeConfig = function() { - var me = this, - config = []; - - config.push( - '[mysqld]', - 'character-set-server = utf8', - 'user = mysql', - 'port = 3306', - 'socket = '+me.options.socketPath, - 'pid-file = '+me.options.pidPath, -// 'log-error = '+me.options.errorLogPath, // disabled due to http://bugs.mysql.com/bug.php?id=65592 -- errors output to STDIN will usually go into emergence-kernel's log - 'basedir = /usr', - 'datadir = '+me.options.dataDir, - 'skip-external-locking', - 'key_buffer_size = 16M', - 'max_allowed_packet = 1M', - 'sort_buffer_size = 512K', - 'net_buffer_length = 8K', - 'read_buffer_size = 256K', - 'read_rnd_buffer_size = 512K', - 'myisam_sort_buffer_size = 8M', -// 'lc-messages-dir = /usr/local/share/mysql', - - 'log-bin = mysqld-bin', - 'expire_logs_days = 2', - 'server-id = 1', - - 'tmpdir = /tmp/', - - 'innodb_buffer_pool_size = 16M', - 'innodb_data_file_path = ibdata1:10M:autoextend:max:128M', - 'innodb_log_file_size = 5M', - 'innodb_log_buffer_size = 8M', - 'innodb_log_files_in_group = 2', - 'innodb_flush_log_at_trx_commit = 1', - 'innodb_lock_wait_timeout = 50', - 'innodb_file_per_table', - 'max_binlog_size = 100M', - 'binlog_format = row' - ); - - if (semver.gt(me.mysqldVersion, '5.6.0')) { - config.push('table_open_cache = 64'); - } else { - config.push('table_cache = 64'); - } - - if (semver.lt(me.mysqldVersion, '5.7.4')) { - config.push('innodb_additional_mem_pool_size = 2M'); - } - - if (me.options.bindHost) { - config.push('bind-address = '+me.options.bindHost); - } else { - config.push('skip-networking'); - } - - return config.join('\n'); -}; exports.MysqlService.prototype.secureInstallation = function() { var me = this, @@ -294,11 +216,7 @@ exports.MysqlService.prototype.secureInstallation = function() { console.log(me.name+': securing installation...'); // set root password - if (semver.lt(me.mysqldVersion, '5.7.0') || me.mysqldIsMaria) { - sql += 'UPDATE mysql.user SET Password=PASSWORD("'+me.options.managerPassword+'") WHERE User="root";'; - } else { - sql += 'UPDATE mysql.user SET authentication_string=PASSWORD("'+me.options.managerPassword+'") WHERE User="root";'; - } + sql += 'UPDATE mysql.user SET Password=PASSWORD("'+me.state.rootPassword+'") WHERE User="root";'; // remove anonymous users sql += 'DELETE FROM mysql.user WHERE User="";'; @@ -315,7 +233,7 @@ exports.MysqlService.prototype.secureInstallation = function() { // open a temporary connection to the new non-secured installation (new mariasql({ - unixSocket: me.options.socketPath, + unixSocket: me.socketPath, user: 'root', password: '', multiStatements: true @@ -334,7 +252,7 @@ exports.MysqlService.prototype.onSiteCreated = function(siteData, requestData, c var me = this, sql = '', dbConfig = { - socket: me.options.socketPath, + socket: me.socketPath, database: siteData.handle, username: siteData.handle, password: me.controller.sites.generatePassword() diff --git a/kernel-lib/services/nginx.js b/kernel-lib/services/nginx.js index b42aba3..9c00ecd 100644 --- a/kernel-lib/services/nginx.js +++ b/kernel-lib/services/nginx.js @@ -14,31 +14,21 @@ exports.NginxService = function(name, controller, options) { // call parent constructor exports.NginxService.super_.apply(me, arguments); - // default options - me.options.configPath = me.options.configPath || controller.options.configDir + '/nginx.conf'; - me.options.execPath = me.options.execPath || '/usr/sbin/nginx'; - me.options.bindHost = me.options.bindHost || '127.0.0.1'; - me.options.bindPort = me.options.bindPort || 80; - me.options.runDir = me.options.runDir || controller.options.runDir + '/nginx'; - me.options.logsDir = me.options.logsDir || controller.options.logsDir + '/nginx'; - me.options.pidPath = me.options.pidPath || me.options.runDir + '/nginx.pid'; - me.options.errorLogPath = me.options.errorLogPath || me.options.logsDir + '/errors.log'; - me.options.miscConfigDir = me.options.miscConfigDir || (process.platform=='darwin'?'/usr/local/etc/nginx':'/etc/nginx'); - me.options.user = me.options.user || controller.options.user; - me.options.group = me.options.group || controller.options.group; - - // create required directories - if (!fs.existsSync(me.options.runDir)) { - fs.mkdirSync(me.options.runDir, '775'); - } + // initialize configuration + me.packagePath = options.packagePath; + me.execPath = me.packagePath + '/bin/nginx'; + + me.configPath = '/hab/svc/emergence-kernel/config/nginx'; + me.sitesConfigPath = '/hab/svc/emergence-kernel/var/config/nginx.sites'; + me.pidPath = '/hab/svc/emergence-kernel/var/run/nginx.pid'; + + me.bindHost = options.bindHost || '127.0.0.1'; + me.bindPort = options.bindPort || 80; - if (!fs.existsSync(me.options.logsDir)) { - fs.mkdirSync(me.options.logsDir, '775'); - } // check for existing master process - if (fs.existsSync(me.options.pidPath)) { - me.pid = parseInt(fs.readFileSync(me.options.pidPath, 'ascii')); + if (fs.existsSync(me.pidPath)) { + me.pid = parseInt(fs.readFileSync(me.pidPath, 'ascii')); console.log(me.name+': found existing PID: '+me.pid); me.status = 'online'; } @@ -57,16 +47,16 @@ util.inherits(exports.NginxService, require('./abstract.js').AbstractService); exports.NginxService.prototype.start = function() { var me = this; - console.log(me.name+': spawning daemon: '+me.options.execPath); + console.log(me.name+': spawning daemon: '+me.execPath); if (me.pid) { console.log(me.name+': already running with PID '+me.pid); return false; } - this.writeConfig(); + this.writeSitesConfig(); - me.proc = spawn(me.options.execPath, ['-c', me.options.configPath]); + me.proc = spawn(me.execPath, ['-c', me.configPath]); me.proc.on('exit', function (code) { @@ -77,16 +67,16 @@ exports.NginxService.prototype.start = function() { } // look for pid - if (fs.existsSync(me.options.pidPath)) { - me.pid = parseInt(fs.readFileSync(me.options.pidPath, 'ascii')); + if (fs.existsSync(me.pidPath)) { + me.pid = parseInt(fs.readFileSync(me.pidPath, 'ascii')); console.log(me.name+': found new PID: '+me.pid); me.status = 'online'; } else { console.log(me.name+': failed to find pid after launching, waiting 1000ms and trying again...'); setTimeout(function() { - if (fs.existsSync(me.options.pidPath)) { - me.pid = parseInt(fs.readFileSync(me.options.pidPath, 'ascii')); + if (fs.existsSync(me.pidPath)) { + me.pid = parseInt(fs.readFileSync(me.pidPath, 'ascii')); console.log(me.name+': found new PID: '+me.pid); me.status = 'online'; } else { @@ -143,7 +133,7 @@ exports.NginxService.prototype.restart = function() { return false; } - this.writeConfig(); + this.writeSitesConfig(); try { process.kill(me.pid, 'SIGHUP'); @@ -158,14 +148,14 @@ exports.NginxService.prototype.restart = function() { }; -exports.NginxService.prototype.writeConfig = function() { - fs.writeFileSync(this.options.configPath, this.makeConfig()); +exports.NginxService.prototype.writeSitesConfig = function() { + fs.writeFileSync(this.sitesConfigPath, this.makeSitesConfig()); }; -exports.NginxService.prototype.makeConfig = function() { +exports.NginxService.prototype.makeSitesConfig = function() { var me = this, - phpSocketPath = me.controller.services['php'].options.socketPath, - phpBootstrapDir = me.controller.services['php'].options.bootstrapDir, + phpSocketPath = me.controller.services['php'].socketPath, + phpBootstrapDir = me.controller.services['php'].bootstrapDir, config = []; // format socket path @@ -173,91 +163,10 @@ exports.NginxService.prototype.makeConfig = function() { phpSocketPath = 'unix:'+phpSocketPath; } - // configure top-level options - config.push( - 'user '+me.options.user+' '+me.options.group+';', - 'worker_processes auto;', - 'pid '+me.options.pidPath+';', - 'error_log '+me.options.errorLogPath+' info;' - ); - - - // configure connection processing - config.push( - 'events {', - ' worker_connections 1024;' - ); - - if (process.platform == 'linux') { - config.push(' use epoll;'); - } - - config.push( - '}' // end events block - ); - - - // configure http options - config.push( - 'http {', - ' include '+me.options.miscConfigDir+'/mime.types;', - ' default_type application/octet-stream;', - - ' log_format main', - ' \'$host $remote_addr - $remote_user [$time_local] \'', - ' \'"$request" $status $bytes_sent \'', - ' \'"$http_referer" "$http_user_agent" \'', - ' \'"$gzip_ratio"\';', - - ' client_header_timeout 10m;', - ' client_body_timeout 10m;', - ' send_timeout 10m;', - - ' connection_pool_size 256;', - ' client_max_body_size 200m;', - ' client_body_buffer_size 128k;', - ' client_header_buffer_size 1k;', - ' large_client_header_buffers 8 512k;', - ' request_pool_size 4k;', - ' server_names_hash_bucket_size 1024;', - ' types_hash_max_size 2048;', - - ' gzip on;', - ' gzip_min_length 1100;', - ' gzip_buffers 4 8k;', - ' gzip_types text/plain text/css text/x-scss text/x-html-template text/x-component text/xml application/xml application/javascript application/json application/php application/atom+xml application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/xhtml+xml font/opentype image/svg+xml image/x-icon;', - - ' output_buffers 1 32k;', - ' postpone_output 1460;', - - ' sendfile on;', - ' tcp_nopush on;', - ' tcp_nodelay on;', - - ' keepalive_timeout 75 20;', - - ' ignore_invalid_headers on;', - - ' index index.php;', - - ' fastcgi_index index.php;', - ' fastcgi_read_timeout 6h;', - ' fastcgi_buffers 32 64k;', - - ' server_tokens off;' -/* - - ' server {', - ' server_name _;', - ' access_log /emergence/logs/access.log main;', - ' error_log /emergence/logs/error.log info;', - ' }', -*/ - ); - + // configure each site _.each(me.controller.sites.sites, function(site, handle) { var hostnames = site.hostnames.slice(), - siteDir = me.controller.sites.options.sitesDir+'/'+handle, + siteDir = me.controller.sites.sitesDir+'/'+handle, logsDir = siteDir+'/logs', siteConfig = [], sslHostnames, sslHostname; @@ -277,9 +186,9 @@ exports.NginxService.prototype.makeConfig = function() { ' error_log '+logsDir+'/error.log notice;', ' location / {', - ' include '+me.options.miscConfigDir+'/fastcgi_params;', - ' fastcgi_param HTTPS $php_https;', ' fastcgi_pass '+phpSocketPath+';', + ' include '+me.packagePath+'/config/fastcgi_params;', + ' fastcgi_param HTTPS $php_https;', ' fastcgi_param PATH_INFO $fastcgi_script_name;', ' fastcgi_param SITE_ROOT '+siteDir+';', ' fastcgi_param SCRIPT_FILENAME '+phpBootstrapDir+'/web.php;', @@ -290,7 +199,7 @@ exports.NginxService.prototype.makeConfig = function() { // append config config.push( ' server {', - ' listen '+me.options.bindHost+':'+me.options.bindPort+';', + ' listen '+me.bindHost+':'+me.bindPort+';', ' server_name '+hostnames.join(' ')+';', ' set $php_https "";' ); @@ -316,7 +225,7 @@ exports.NginxService.prototype.makeConfig = function() { for (sslHostname in sslHostnames) { config.push( ' server {', - ' listen '+me.options.bindHost+':443;', + ' listen '+me.bindHost+':443;', ' server_name '+sslHostname+';', ' set $php_https on;', @@ -333,10 +242,6 @@ exports.NginxService.prototype.makeConfig = function() { } }); - config.push( - '}' // end http block - ); - return config.join('\n'); }; diff --git a/kernel-lib/services/php-fpm.js b/kernel-lib/services/php-fpm.js index 008e021..f35ff11 100644 --- a/kernel-lib/services/php-fpm.js +++ b/kernel-lib/services/php-fpm.js @@ -15,31 +15,22 @@ exports.PhpFpmService = function(name, controller, options) { // call parent constructor exports.PhpFpmService.super_.apply(me, arguments); - // default options - me.options.bootstrapDir = me.options.bootstrapDir || path.resolve(__dirname, '../../php-bootstrap'); - me.options.configPath = me.options.configPath || controller.options.configDir + '/php-fpm.conf'; - me.options.execPath = me.options.execPath || '/usr/bin/php-fpm'; - me.options.statScripts = me.options.statScripts || false; - me.options.runDir = me.options.runDir || controller.options.runDir + '/php-fpm'; - me.options.logsDir = me.options.logsDir || controller.options.logsDir + '/php-fpm'; - me.options.pidPath = me.options.pidPath || me.options.runDir + '/php-fpm.pid'; - me.options.socketPath = me.options.socketPath || me.options.runDir + '/php-fpm.sock'; - me.options.errorLogPath = me.options.errorLogPath || me.options.logsDir + '/errors.log'; - me.options.user = me.options.user || controller.options.user; - me.options.group = me.options.group || controller.options.group; - - // create required directories - if (!fs.existsSync(me.options.runDir)) { - fs.mkdirSync(me.options.runDir, '775'); - } + // initialize configuration + me.packagePath = options.packagePath; + me.execPath = me.packagePath + '/sbin/php-fpm'; + + me.phpConfigPath = '/hab/svc/emergence-kernel/config/php.ini'; + me.fpmConfigPath = '/hab/svc/emergence-kernel/config/php-fpm'; + me.pidPath = '/hab/svc/emergence-kernel/var/run/php-fpm.pid'; + me.socketPath = '/hab/svc/emergence-kernel/var/run/php-fpm.sock'; + me.errorLogPath = '/hab/svc/emergence-kernel/var/log/php-fpm.err'; + me.dataDir = '/hab/svc/emergence-kernel/var/mariadb'; + me.bootstrapDir = '/hab/svc/emergence-kernel/static/php-bootstrap'; - if (!fs.existsSync(me.options.logsDir)) { - fs.mkdirSync(me.options.logsDir, '775'); - } // check for existing master process - if (fs.existsSync(me.options.pidPath)) { - me.pid = parseInt(fs.readFileSync(me.options.pidPath, 'ascii')); + if (fs.existsSync(me.pidPath)) { + me.pid = parseInt(fs.readFileSync(me.pidPath, 'ascii')); console.log(me.name+': found existing PID: '+me.pid); me.status = 'online'; } @@ -55,16 +46,14 @@ util.inherits(exports.PhpFpmService, require('./abstract.js').AbstractService); exports.PhpFpmService.prototype.start = function() { var me = this; - console.log(me.name+': spawning daemon: '+me.options.execPath); + console.log(me.name+': spawning daemon: '+me.execPath); if (me.pid) { console.log(me.name+': already running with PID '+me.pid); return false; } - this.writeConfig(); - - me.proc = spawn(me.options.execPath, ['--fpm-config', me.options.configPath]); + me.proc = spawn(me.execPath, ['-c', me.phpConfigPath, '--fpm-config', me.fpmConfigPath]); me.proc.on('exit', function (code) { @@ -75,8 +64,8 @@ exports.PhpFpmService.prototype.start = function() { } // look for pid - if (fs.existsSync(me.options.pidPath)) { - me.pid = parseInt(fs.readFileSync(me.options.pidPath, 'ascii')); + if (fs.existsSync(me.pidPath)) { + me.pid = parseInt(fs.readFileSync(me.pidPath, 'ascii')); console.log(me.name+': found new PID: '+me.pid); me.status = 'online'; } else { @@ -131,8 +120,6 @@ exports.PhpFpmService.prototype.restart = function() { return false; } - this.writeConfig(); - try { process.kill(me.pid, 'SIGUSR2'); } catch (error) { @@ -146,67 +133,17 @@ exports.PhpFpmService.prototype.restart = function() { }; -exports.PhpFpmService.prototype.writeConfig = function() { - fs.writeFileSync(this.options.configPath, this.makeConfig()); -}; - -exports.PhpFpmService.prototype.makeConfig = function() { - var me = this, - config = []; - - config.push( - '[global]', - 'pid = '+me.options.pidPath, - 'error_log = '+me.options.errorLogPath - ); - - config.push( - '[www]', - 'user = '+me.options.user, - 'group = '+me.options.group, - 'catch_workers_output = on', - 'listen = '+me.options.socketPath, - 'listen.owner = '+me.options.user, - 'listen.group = '+me.options.group, - 'pm = dynamic', - 'pm.max_children = '+(me.options.maxClients||50), - 'pm.start_servers = '+(me.options.startServers||5), - 'pm.min_spare_servers = '+(me.options.minSpareServers||1), - 'pm.max_spare_servers = '+Math.round((me.options.maxClients||50)/(me.options.startServers||5)) - ); - - if (me.options.statusPath) { - config.push('pm.status_path = '+me.options.statusPath); - } - - config.push( - 'php_admin_flag[short_open_tag] = on', - 'php_admin_value[apc.shm_size] = 512M', - 'php_admin_value[apc.shm_segments] = 1', - 'php_admin_value[apc.slam_defense] = 0', - 'php_admin_value[apc.stat] = '+(me.options.statScripts?'1':'0'), - 'php_admin_value[opcache.validate_timestamps] = '+(me.options.statScripts?'1':'0'), - 'php_admin_value[upload_max_filesize] = '+(me.options.uploadMaxSize ? me.options.uploadMaxSize : '200M'), - 'php_admin_value[post_max_size] = '+(me.options.postMaxSize ? me.options.postMaxSize : '200M'), - 'php_admin_value[memory_limit] = '+(me.options.memoryLimit ? me.options.memoryLimit : '200M'), - 'php_admin_value[error_reporting] = '+(me.options.errorReporting ? me.options.errorReporting : 'E_ALL & ~E_NOTICE'), - 'php_admin_value[date.timezone] = '+(me.options.defaultTimezone ? me.options.defaultTimezone : 'America/New_York') - ); - - return config.join('\n'); -}; - exports.PhpFpmService.prototype.onSiteUpdated = function(siteData) { var me = this, - siteRoot = me.controller.sites.options.sitesDir + '/' + siteData.handle, + siteRoot = me.controller.sites.sitesDir + '/' + siteData.handle, phpClient; console.log(me.name+': clearing config cache for '+siteRoot); // Connect to FPM worker pool phpClient = new phpfpm({ - sockFile: me.options.socketPath, - documentRoot: me.options.bootstrapDir + '/' + sockFile: me.socketPath, + documentRoot: me.bootstrapDir + '/' }); // Clear cached site.json diff --git a/kernel-lib/sites.js b/kernel-lib/sites.js index 956d58f..488dc60 100644 --- a/kernel-lib/sites.js +++ b/kernel-lib/sites.js @@ -6,7 +6,6 @@ var _ = require('underscore'), events = require('events'), posix = require('posix'), spawn = require('child_process').spawn, - hostile = require('hostile'), phpShellScript = path.resolve(__dirname, '../bin/shell'); @@ -21,25 +20,19 @@ exports.Sites = function(config) { // call events constructor events.EventEmitter.call(me); - // initialize options and apply defaults - me.options = options || {}; - me.options.sitesDir = me.options.sitesDir || '/emergence/sites'; - me.options.dataUID = me.options.dataUID || posix.getpwnam(config.user).uid; - me.options.dataGID = me.options.dataGID || posix.getgrnam(config.group).gid; - me.options.dataMode = me.options.dataMode || '775'; + // initialize configuration + me.sitesDir = '/hab/svc/emergence-kernel/data/sites'; + me.dataUid = posix.getpwnam('hab').uid; + me.dataGid = posix.getgrnam('hab').gid; - // create required directories - if (!fs.existsSync(me.options.sitesDir)) { - fs.mkdirSync(me.options.sitesDir, '775'); - } // load sites - console.log('Loading sites from '+me.options.sitesDir+'...'); + console.log('Loading sites from '+me.sitesDir+'...'); me.sites = {}; - _.each(fs.readdirSync(me.options.sitesDir), function(handle) { + _.each(fs.readdirSync(me.sitesDir), function(handle) { try { - me.sites[handle] = JSON.parse(fs.readFileSync(me.options.sitesDir+'/'+handle+'/site.json', 'ascii')); + me.sites[handle] = JSON.parse(fs.readFileSync(me.sitesDir+'/'+handle+'/site.json', 'ascii')); me.sites[handle].handle = handle; console.log('-Loaded: '+me.sites[handle].primary_hostname); } catch (error) { @@ -86,7 +79,7 @@ exports.Sites.prototype.handleRequest = function(request, response, server) { } var handle = request.path[1], - siteDir = me.options.sitesDir + '/' + handle, + siteDir = me.sitesDir + '/' + handle, siteConfigPath = siteDir + '/site.json', params = JSON.parse(request.content), siteData; @@ -145,7 +138,7 @@ exports.Sites.prototype.handleRequest = function(request, response, server) { console.log('Executing shell post for ' + request.path[1] + ':'); console.log(requestData); - phpProc = spawn(phpShellScript, [request.path[1]]); + phpProc = spawn(phpShellScript, [request.path[1]], { uid: me.dataUid, gid: me.dataGid }); phpProcInitialized = false; phpProc.stderr.on('data', function(data) { @@ -178,7 +171,7 @@ exports.Sites.prototype.handleRequest = function(request, response, server) { console.log('Creating developer for ' + request.path[1] + ':' + phpShellScript); response.writeHead(200, {'Content-Type':'application/json'}); - phpProc = spawn(phpShellScript, [request.path[1], '--stdin']); + phpProc = spawn(phpShellScript, [request.path[1], '--stdin'], { uid: me.dataUid, gid: me.dataGid }); phpProc.stdout.on('data', function(data) { console.log('php-cli stdout: ' + data); @@ -220,16 +213,12 @@ exports.Sites.prototype.handleRequest = function(request, response, server) { cfgResult = me.writeSiteConfig(requestData); if (cfgResult.isNew) { - // write primary hostname to /etc/hosts - hostile.set('127.0.0.1', cfgResult.site.primary_hostname); - console.log('added ' + cfgResult.site.primary_hostname + ' to /etc/hosts'); - // notify plugins me.emit('siteCreated', cfgResult.site, requestData, { databaseReady: function() { // execute onSiteCreated within site's container console.log('Executing Site::onSiteCreated() via php-cli'); - phpProc = spawn(phpShellScript, [cfgResult.site.handle]); + phpProc = spawn(phpShellScript, [cfgResult.site.handle], { uid: me.dataUid, gid: me.dataGid }); phpProc.stdout.on('data', function(data) { console.log('php-cli stdout: ' + data); }); phpProc.stderr.on('data', function(data) { console.log('php-cli stderr: ' + data); }); @@ -307,7 +296,7 @@ exports.Sites.prototype.writeSiteConfig = function(requestData) { } // create site directory - var siteDir = me.options.sitesDir+'/'+siteData.handle, + var siteDir = me.sitesDir+'/'+siteData.handle, dataDir = siteDir + '/data', siteDataDir = siteDir + '/site-data', siteConfigPath = siteDir + '/site.json'; @@ -318,13 +307,13 @@ exports.Sites.prototype.writeSiteConfig = function(requestData) { } if (!fs.existsSync(dataDir)) { - fs.mkdirSync(dataDir, me.options.dataMode); - fs.chownSync(dataDir, me.options.dataUID, me.options.dataGID); + fs.mkdirSync(dataDir, '775'); + fs.chownSync(dataDir, me.dataUid, me.dataGid); } if (!fs.existsSync(siteDataDir)) { - fs.mkdirSync(siteDataDir, me.options.dataMode); - fs.chownSync(siteDataDir, me.options.dataUID, me.options.dataGID); + fs.mkdirSync(siteDataDir, '775'); + fs.chownSync(siteDataDir, me.dataUid, me.dataGid); } // write site config to file @@ -341,7 +330,7 @@ exports.Sites.prototype.writeSiteConfig = function(requestData) { exports.Sites.prototype.updateSiteConfig = function(handle, changes) { var me = this, - siteDir = me.options.sitesDir+'/'+handle, + siteDir = me.sitesDir+'/'+handle, filename = siteDir+'/site.json', siteData = this.sites[handle], create_user; diff --git a/package.json b/package.json index 01ebf42..eb80d45 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,17 @@ { "name": "emergence", "preferGlobal": true, - "version": "0.0.3", + "version": "1.0.0", "license": "MIT", + "engines": { + "node": "6.10.3" + }, "dependencies": { "underscore": "1.3.x", "mariasql": "^0.2.6", "node-static": "0.6.x", "http-auth": "1.2.7", "posix": "^4.0.2", - "hostile": "^1.0.2", "shelljs": "^0.5.3", "semver": "^5.1.0", "underscore-cli": "^0.2.19", @@ -25,5 +27,8 @@ "repository": { "type": "git", "url": "https://github.com/JarvusInnovations/Emergence.git" + }, + "scripts": { + "start": "node bin/kernel" } } diff --git a/php-bootstrap/lib/Site.class.php b/php-bootstrap/lib/Site.class.php index 626d0e2..55a95b1 100644 --- a/php-bootstrap/lib/Site.class.php +++ b/php-bootstrap/lib/Site.class.php @@ -165,19 +165,19 @@ public static function handleRequest() } // handle CORS headers - if (isset($_SERVER['HTTP_ORIGIN'])) { - $hostname = strtolower(parse_url($_SERVER['HTTP_ORIGIN'], PHP_URL_HOST)); - if ($hostname == strtolower(static::$hostname) || static::$permittedOrigins == '*' || in_array($hostname, static::$permittedOrigins)) { - header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); - header('Access-Control-Allow-Credentials: true'); - //header('Access-Control-Max-Age: 86400') - } else { - header('HTTP/1.1 403 Forbidden'); - exit(); + if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) { + if (isset($_SERVER['HTTP_ORIGIN'])) { + $hostname = strtolower(parse_url($_SERVER['HTTP_ORIGIN'], PHP_URL_HOST)); + if ($hostname == strtolower(static::$hostname) || static::$permittedOrigins == '*' || in_array($hostname, static::$permittedOrigins)) { + header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); + header('Access-Control-Allow-Credentials: true'); + //header('Access-Control-Max-Age: 86400') + } else { + header('HTTP/1.1 403 Forbidden'); + die('CORS access denied for given origin'); + } } - } - if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) { header('Access-Control-Allow-Methods: ' . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']); if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) { diff --git a/php-bootstrap/mail.php b/php-bootstrap/mail.php index 92cffbe..b3e00a0 100644 --- a/php-bootstrap/mail.php +++ b/php-bootstrap/mail.php @@ -10,26 +10,26 @@ // get hostmap // TODO: have the kernel maintain this file -$hostmapPath = '/emergence/services/hostmap.inc.php'; +$hostmapPath = '/hab/svc/emergence-kernel/var/hostmap.inc.php'; if (is_readable($hostmapPath)) { $hostmap = require($hostmapPath); } else { $hostmap = []; - - foreach (glob('/emergence/sites/*', GLOB_ONLYDIR) AS $sitePath) { + + foreach (glob('/hab/svc/emergence-kernel/data/sites/*', GLOB_ONLYDIR) AS $sitePath) { $configPath = "$sitePath/site.json"; if (!is_readable($configPath)) { continue; } - + $config = @json_decode(file_get_contents($configPath), true); - + if (!$config) { continue; } - + $hostnames = array_unique(array_merge([$config['primary_hostname']], $config['hostnames'])); - + foreach ($hostnames AS $hostname) { $hostmap['/^' . str_replace('\\*', '.*', preg_quote($hostname)) . '$/i'] = basename($sitePath); } @@ -58,7 +58,7 @@ // bootstrap emergence require('bootstrap.inc.php'); Site::$debug = true; -Site::initialize("/emergence/sites/$siteHandle", $hostname); +Site::initialize("/hab/svc/emergence-kernel/data/sites/$siteHandle", $hostname); // delegate remainder of request to email router diff --git a/rebuild.sh b/rebuild.sh new file mode 100755 index 0000000..c48424a --- /dev/null +++ b/rebuild.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# reset runtime env +./clean-runtime.sh + +rm -R /hab/svc/*/ + +exec build \ No newline at end of file diff --git a/reset-emergence.sh b/reset-emergence.sh new file mode 100755 index 0000000..0d656db --- /dev/null +++ b/reset-emergence.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +./clean-runtime.sh +rm -R /hab/svc/emergence-kernel \ No newline at end of file diff --git a/run-kernel.sh b/run-kernel.sh new file mode 100755 index 0000000..365d6af --- /dev/null +++ b/run-kernel.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +./clean-runtime.sh + +export NODE_PATH="`hab pkg path emergence/emergence-kernel`/app/node_modules/" + +exec hab pkg exec core/node node bin/kernel \ No newline at end of file diff --git a/run-service.sh b/run-service.sh new file mode 100755 index 0000000..42167f0 --- /dev/null +++ b/run-service.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +./clean-runtime.sh + +exec hab svc start emergence/emergence-kernel \ No newline at end of file diff --git a/run-studio.sh b/run-studio.sh new file mode 100755 index 0000000..59daa06 --- /dev/null +++ b/run-studio.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +export HAB_DOCKER_OPTS="-p 9080:80 -p 9083:9083" +export HAB_ORIGIN=emergence + +exec hab studio enter diff --git a/service-plans/mariadb/config/init.sql b/service-plans/mariadb/config/init.sql new file mode 100644 index 0000000..8c34743 --- /dev/null +++ b/service-plans/mariadb/config/init.sql @@ -0,0 +1,6 @@ +UPDATE mysql.user SET Password=PASSWORD('{{cfg.root_password}}') WHERE User='root'; +DELETE FROM mysql.user WHERE User=''; +DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1'); +DROP DATABASE IF EXISTS test; +DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'; +FLUSH PRIVILEGES; \ No newline at end of file diff --git a/service-plans/mariadb/config/my.cnf b/service-plans/mariadb/config/my.cnf new file mode 100644 index 0000000..b03580e --- /dev/null +++ b/service-plans/mariadb/config/my.cnf @@ -0,0 +1,23 @@ +[mysqld_safe] +pid-file = {{pkg.svc_var_path}}/mysqld.pid +socket = {{pkg.svc_var_path}}/mysqld.sock +nice = 0 + +[mysqld] +port = {{cfg.port}} +socket = {{pkg.svc_var_path}}/mysqld.sock +datadir = {{pkg.svc_data_path}} +pid-file = {{pkg.svc_var_path}}/mysqld.pid +log-error = mysqld-err.log +log-isam = mysqld-isam.log +log-tc = mysqld-tc.log +aria-log-dir-path = {{pkg.svc_data_path}}/mysqld-aria +master-info-file = mysqld-master.info +{{~#if cfg.general_log}} +general-log = TRUE +general-log-file = {{pkg.svc_var_path}}/mysqld.log +{{~/if}} +{{~#if cfg.bind_address}} +bind-address = {{cfg.bind_address}} +{{~/if}} +init-file = {{pkg.svc_config_path}}/init.sql \ No newline at end of file diff --git a/service-plans/mariadb/default.toml b/service-plans/mariadb/default.toml new file mode 100644 index 0000000..52a153a --- /dev/null +++ b/service-plans/mariadb/default.toml @@ -0,0 +1,4 @@ +root_password = "" +port = 3306 +bind_address = "127.0.0.1" +general_log = true \ No newline at end of file diff --git a/service-plans/mariadb/hooks/init b/service-plans/mariadb/hooks/init new file mode 100644 index 0000000..e5a3270 --- /dev/null +++ b/service-plans/mariadb/hooks/init @@ -0,0 +1,14 @@ +#!/bin/sh + +exec 2>&1 + +#mariadb aria files folder +mkdir -p {{pkg.svc_data_path}}/mysqld-aria + +#mariadb needs to create 'mysql' database +if [ ! -f {{pkg.svc_files_path}}/db_installed ]; then + cd {{pkg.path}} && \ + scripts/mysql_install_db --defaults-file={{pkg.svc_config_path}}/my.cnf \ + --user={{pkg.svc_user}} > \ + {{pkg.svc_files_path}}/db_installed +fi \ No newline at end of file diff --git a/service-plans/mariadb/hooks/run b/service-plans/mariadb/hooks/run new file mode 100644 index 0000000..fffcd13 --- /dev/null +++ b/service-plans/mariadb/hooks/run @@ -0,0 +1,7 @@ +#!/bin/sh + +exec 2>&1 + +#start the mysql server +mysqld_safe --defaults-file={{pkg.svc_config_path}}/my.cnf \ + --user={{pkg.svc_user}} \ No newline at end of file diff --git a/service-plans/mariadb/plan.sh b/service-plans/mariadb/plan.sh new file mode 100644 index 0000000..ab6bf42 --- /dev/null +++ b/service-plans/mariadb/plan.sh @@ -0,0 +1,49 @@ +pkg_name=mariadb +pkg_origin=emergence +pkg_version=10.2.6 +pkg_description="An open source monitoring software for networks and applications" +pkg_maintainer="The Habitat Maintainers " +pkg_license=('GPL-2.0') +pkg_source=https://github.com/MariaDB/server/archive/${pkg_name}-${pkg_version}.tar.gz +pkg_shasum=64dc9152daee2b396828963298edc55f36ad1add65a1f19d3db5ff0962d46842 +pkg_dirname="server-${pkg_name}-${pkg_version}" +pkg_deps=(core/ncurses core/gcc-libs core/zlib core/sed) +pkg_build_deps=(core/gcc core/make core/coreutils core/cmake) +pkg_bin_dirs=(bin) +pkg_include_dirs=(include) +pkg_lib_dirs=(lib) +pkg_exports=( + [port]=port +) +pkg_exposes=(port) +pkg_svc_user="hab" + +do_prepare() { + if [ -f CMakeCache.txt ]; then + rm CMakeCache.txt + fi + + sed -i 's/^.*abi_check.*$/#/' CMakeLists.txt + sed -i "s@data/test@\${INSTALL_MYSQLTESTDIR}@g" sql/CMakeLists.txt + export CXXFLAGS="$CFLAGS" +} + +do_build() { + cmake . -DCMAKE_INSTALL_PREFIX="${pkg_prefix}" \ + -DCMAKE_PREFIX_PATH="$(pkg_path_for core/ncurses)" \ + -DCMAKE_BUILD_TYPE=Release \ + -DWITH_READLINE=OFF + + make + + return $? +} + +do_install() { + attach + make install + attach + rm -rf "${pkg_prefix}/mysql-test" + rm -rf "${pkg_prefix}/bin/mysql_client_test" + rm -rf "${pkg_prefix}/bin/mysql_test" +} diff --git a/service-plans/nginx/config/fastcgi.conf b/service-plans/nginx/config/fastcgi.conf new file mode 100644 index 0000000..ac9ff92 --- /dev/null +++ b/service-plans/nginx/config/fastcgi.conf @@ -0,0 +1,25 @@ + +fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param HTTPS $https if_not_empty; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; diff --git a/service-plans/nginx/config/fastcgi_params b/service-plans/nginx/config/fastcgi_params new file mode 100644 index 0000000..71e2c2e --- /dev/null +++ b/service-plans/nginx/config/fastcgi_params @@ -0,0 +1,24 @@ + +fastcgi_param QUERY_STRING $query_string; +fastcgi_param REQUEST_METHOD $request_method; +fastcgi_param CONTENT_TYPE $content_type; +fastcgi_param CONTENT_LENGTH $content_length; + +fastcgi_param SCRIPT_NAME $fastcgi_script_name; +fastcgi_param REQUEST_URI $request_uri; +fastcgi_param DOCUMENT_URI $document_uri; +fastcgi_param DOCUMENT_ROOT $document_root; +fastcgi_param SERVER_PROTOCOL $server_protocol; +fastcgi_param HTTPS $https if_not_empty; + +fastcgi_param GATEWAY_INTERFACE CGI/1.1; +fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + +fastcgi_param REMOTE_ADDR $remote_addr; +fastcgi_param REMOTE_PORT $remote_port; +fastcgi_param SERVER_ADDR $server_addr; +fastcgi_param SERVER_PORT $server_port; +fastcgi_param SERVER_NAME $server_name; + +# PHP only, required if PHP was built with --enable-force-cgi-redirect +fastcgi_param REDIRECT_STATUS 200; diff --git a/service-plans/nginx/config/http.include b/service-plans/nginx/config/http.include new file mode 100644 index 0000000..f73384f --- /dev/null +++ b/service-plans/nginx/config/http.include @@ -0,0 +1,15 @@ +include mime.types; +default_type application/octet-stream; + +sendfile {{cfg.http.sendfile}}; +tcp_nopush {{cfg.http.tcp_nopush}}; +tcp_nodelay {{cfg.http.tcp_nodelay}}; + +keepalive_timeout {{cfg.http.keepalive_timeout}}; + +gzip on; +gzip_vary on; +gzip_min_length 10240; +gzip_proxied expired no-cache no-store private auth; +gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml; +gzip_disable "MSIE [1-6]\."; \ No newline at end of file diff --git a/service-plans/nginx/config/koi-utf b/service-plans/nginx/config/koi-utf new file mode 100644 index 0000000..e7974ff --- /dev/null +++ b/service-plans/nginx/config/koi-utf @@ -0,0 +1,109 @@ + +# This map is not a full koi8-r <> utf8 map: it does not contain +# box-drawing and some other characters. Besides this map contains +# several koi8-u and Byelorussian letters which are not in koi8-r. +# If you need a full and standard map, use contrib/unicode2nginx/koi-utf +# map instead. + +charset_map koi8-r utf-8 { + + 80 E282AC ; # euro + + 95 E280A2 ; # bullet + + 9A C2A0 ; #   + + 9E C2B7 ; # · + + A3 D191 ; # small yo + A4 D194 ; # small Ukrainian ye + + A6 D196 ; # small Ukrainian i + A7 D197 ; # small Ukrainian yi + + AD D291 ; # small Ukrainian soft g + AE D19E ; # small Byelorussian short u + + B0 C2B0 ; # ° + + B3 D081 ; # capital YO + B4 D084 ; # capital Ukrainian YE + + B6 D086 ; # capital Ukrainian I + B7 D087 ; # capital Ukrainian YI + + B9 E28496 ; # numero sign + + BD D290 ; # capital Ukrainian soft G + BE D18E ; # capital Byelorussian short U + + BF C2A9 ; # (C) + + C0 D18E ; # small yu + C1 D0B0 ; # small a + C2 D0B1 ; # small b + C3 D186 ; # small ts + C4 D0B4 ; # small d + C5 D0B5 ; # small ye + C6 D184 ; # small f + C7 D0B3 ; # small g + C8 D185 ; # small kh + C9 D0B8 ; # small i + CA D0B9 ; # small j + CB D0BA ; # small k + CC D0BB ; # small l + CD D0BC ; # small m + CE D0BD ; # small n + CF D0BE ; # small o + + D0 D0BF ; # small p + D1 D18F ; # small ya + D2 D180 ; # small r + D3 D181 ; # small s + D4 D182 ; # small t + D5 D183 ; # small u + D6 D0B6 ; # small zh + D7 D0B2 ; # small v + D8 D18C ; # small soft sign + D9 D18B ; # small y + DA D0B7 ; # small z + DB D188 ; # small sh + DC D18D ; # small e + DD D189 ; # small shch + DE D187 ; # small ch + DF D18A ; # small hard sign + + E0 D0AE ; # capital YU + E1 D090 ; # capital A + E2 D091 ; # capital B + E3 D0A6 ; # capital TS + E4 D094 ; # capital D + E5 D095 ; # capital YE + E6 D0A4 ; # capital F + E7 D093 ; # capital G + E8 D0A5 ; # capital KH + E9 D098 ; # capital I + EA D099 ; # capital J + EB D09A ; # capital K + EC D09B ; # capital L + ED D09C ; # capital M + EE D09D ; # capital N + EF D09E ; # capital O + + F0 D09F ; # capital P + F1 D0AF ; # capital YA + F2 D0A0 ; # capital R + F3 D0A1 ; # capital S + F4 D0A2 ; # capital T + F5 D0A3 ; # capital U + F6 D096 ; # capital ZH + F7 D092 ; # capital V + F8 D0AC ; # capital soft sign + F9 D0AB ; # capital Y + FA D097 ; # capital Z + FB D0A8 ; # capital SH + FC D0AD ; # capital E + FD D0A9 ; # capital SHCH + FE D0A7 ; # capital CH + FF D0AA ; # capital hard sign +} diff --git a/service-plans/nginx/config/koi-win b/service-plans/nginx/config/koi-win new file mode 100644 index 0000000..72afabe --- /dev/null +++ b/service-plans/nginx/config/koi-win @@ -0,0 +1,103 @@ + +charset_map koi8-r windows-1251 { + + 80 88 ; # euro + + 95 95 ; # bullet + + 9A A0 ; #   + + 9E B7 ; # · + + A3 B8 ; # small yo + A4 BA ; # small Ukrainian ye + + A6 B3 ; # small Ukrainian i + A7 BF ; # small Ukrainian yi + + AD B4 ; # small Ukrainian soft g + AE A2 ; # small Byelorussian short u + + B0 B0 ; # ° + + B3 A8 ; # capital YO + B4 AA ; # capital Ukrainian YE + + B6 B2 ; # capital Ukrainian I + B7 AF ; # capital Ukrainian YI + + B9 B9 ; # numero sign + + BD A5 ; # capital Ukrainian soft G + BE A1 ; # capital Byelorussian short U + + BF A9 ; # (C) + + C0 FE ; # small yu + C1 E0 ; # small a + C2 E1 ; # small b + C3 F6 ; # small ts + C4 E4 ; # small d + C5 E5 ; # small ye + C6 F4 ; # small f + C7 E3 ; # small g + C8 F5 ; # small kh + C9 E8 ; # small i + CA E9 ; # small j + CB EA ; # small k + CC EB ; # small l + CD EC ; # small m + CE ED ; # small n + CF EE ; # small o + + D0 EF ; # small p + D1 FF ; # small ya + D2 F0 ; # small r + D3 F1 ; # small s + D4 F2 ; # small t + D5 F3 ; # small u + D6 E6 ; # small zh + D7 E2 ; # small v + D8 FC ; # small soft sign + D9 FB ; # small y + DA E7 ; # small z + DB F8 ; # small sh + DC FD ; # small e + DD F9 ; # small shch + DE F7 ; # small ch + DF FA ; # small hard sign + + E0 DE ; # capital YU + E1 C0 ; # capital A + E2 C1 ; # capital B + E3 D6 ; # capital TS + E4 C4 ; # capital D + E5 C5 ; # capital YE + E6 D4 ; # capital F + E7 C3 ; # capital G + E8 D5 ; # capital KH + E9 C8 ; # capital I + EA C9 ; # capital J + EB CA ; # capital K + EC CB ; # capital L + ED CC ; # capital M + EE CD ; # capital N + EF CE ; # capital O + + F0 CF ; # capital P + F1 DF ; # capital YA + F2 D0 ; # capital R + F3 D1 ; # capital S + F4 D2 ; # capital T + F5 D3 ; # capital U + F6 C6 ; # capital ZH + F7 C2 ; # capital V + F8 DC ; # capital soft sign + F9 DB ; # capital Y + FA C7 ; # capital Z + FB D8 ; # capital SH + FC DD ; # capital E + FD D9 ; # capital SHCH + FE D7 ; # capital CH + FF DA ; # capital hard sign +} diff --git a/service-plans/nginx/config/mime.types b/service-plans/nginx/config/mime.types new file mode 100644 index 0000000..89be9a4 --- /dev/null +++ b/service-plans/nginx/config/mime.types @@ -0,0 +1,89 @@ + +types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/png png; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + image/svg+xml svg svgz; + image/webp webp; + + application/font-woff woff; + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.wap.wmlc wmlc; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xspf+xml xspf; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; + application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} diff --git a/service-plans/nginx/config/nginx.conf b/service-plans/nginx/config/nginx.conf new file mode 100644 index 0000000..fd8526e --- /dev/null +++ b/service-plans/nginx/config/nginx.conf @@ -0,0 +1,15 @@ +include worker.include; + +http { + include http.include; + + server { + listen {{cfg.http.listen.port}}; + server_name localhost; + + location / { + root {{pkg.svc_data_path}}; + index index.html index.htm; + } + } +} diff --git a/service-plans/nginx/config/scgi_params b/service-plans/nginx/config/scgi_params new file mode 100644 index 0000000..47348ca --- /dev/null +++ b/service-plans/nginx/config/scgi_params @@ -0,0 +1,16 @@ + +scgi_param REQUEST_METHOD $request_method; +scgi_param REQUEST_URI $request_uri; +scgi_param QUERY_STRING $query_string; +scgi_param CONTENT_TYPE $content_type; + +scgi_param DOCUMENT_URI $document_uri; +scgi_param DOCUMENT_ROOT $document_root; +scgi_param SCGI 1; +scgi_param SERVER_PROTOCOL $server_protocol; +scgi_param HTTPS $https if_not_empty; + +scgi_param REMOTE_ADDR $remote_addr; +scgi_param REMOTE_PORT $remote_port; +scgi_param SERVER_PORT $server_port; +scgi_param SERVER_NAME $server_name; diff --git a/service-plans/nginx/config/uwsgi_params b/service-plans/nginx/config/uwsgi_params new file mode 100644 index 0000000..f539451 --- /dev/null +++ b/service-plans/nginx/config/uwsgi_params @@ -0,0 +1,16 @@ + +uwsgi_param QUERY_STRING $query_string; +uwsgi_param REQUEST_METHOD $request_method; +uwsgi_param CONTENT_TYPE $content_type; +uwsgi_param CONTENT_LENGTH $content_length; + +uwsgi_param REQUEST_URI $request_uri; +uwsgi_param PATH_INFO $document_uri; +uwsgi_param DOCUMENT_ROOT $document_root; +uwsgi_param SERVER_PROTOCOL $server_protocol; +uwsgi_param HTTPS $https if_not_empty; + +uwsgi_param REMOTE_ADDR $remote_addr; +uwsgi_param REMOTE_PORT $remote_port; +uwsgi_param SERVER_PORT $server_port; +uwsgi_param SERVER_NAME $server_name; diff --git a/service-plans/nginx/config/win-utf b/service-plans/nginx/config/win-utf new file mode 100644 index 0000000..391b335 --- /dev/null +++ b/service-plans/nginx/config/win-utf @@ -0,0 +1,125 @@ +# This map is not a full windows-1251 <> utf8 map: it does not +# contain Serbian and Macedonian letters. If you need a full map, +# use contrib/unicode2nginx/win-utf map instead. + +charset_map windows-1251 utf-8 { + + 82 E2809A ; # single low-9 quotation mark + + 84 E2809E ; # double low-9 quotation mark + 85 E280A6 ; # ellipsis + 86 E280A0 ; # dagger + 87 E280A1 ; # double dagger + 88 E282AC ; # euro + 89 E280B0 ; # per mille + + 91 E28098 ; # left single quotation mark + 92 E28099 ; # right single quotation mark + 93 E2809C ; # left double quotation mark + 94 E2809D ; # right double quotation mark + 95 E280A2 ; # bullet + 96 E28093 ; # en dash + 97 E28094 ; # em dash + + 99 E284A2 ; # trade mark sign + + A0 C2A0 ; #   + A1 D18E ; # capital Byelorussian short U + A2 D19E ; # small Byelorussian short u + + A4 C2A4 ; # currency sign + A5 D290 ; # capital Ukrainian soft G + A6 C2A6 ; # borken bar + A7 C2A7 ; # section sign + A8 D081 ; # capital YO + A9 C2A9 ; # (C) + AA D084 ; # capital Ukrainian YE + AB C2AB ; # left-pointing double angle quotation mark + AC C2AC ; # not sign + AD C2AD ; # soft hypen + AE C2AE ; # (R) + AF D087 ; # capital Ukrainian YI + + B0 C2B0 ; # ° + B1 C2B1 ; # plus-minus sign + B2 D086 ; # capital Ukrainian I + B3 D196 ; # small Ukrainian i + B4 D291 ; # small Ukrainian soft g + B5 C2B5 ; # micro sign + B6 C2B6 ; # pilcrow sign + B7 C2B7 ; # · + B8 D191 ; # small yo + B9 E28496 ; # numero sign + BA D194 ; # small Ukrainian ye + BB C2BB ; # right-pointing double angle quotation mark + + BF D197 ; # small Ukrainian yi + + C0 D090 ; # capital A + C1 D091 ; # capital B + C2 D092 ; # capital V + C3 D093 ; # capital G + C4 D094 ; # capital D + C5 D095 ; # capital YE + C6 D096 ; # capital ZH + C7 D097 ; # capital Z + C8 D098 ; # capital I + C9 D099 ; # capital J + CA D09A ; # capital K + CB D09B ; # capital L + CC D09C ; # capital M + CD D09D ; # capital N + CE D09E ; # capital O + CF D09F ; # capital P + + D0 D0A0 ; # capital R + D1 D0A1 ; # capital S + D2 D0A2 ; # capital T + D3 D0A3 ; # capital U + D4 D0A4 ; # capital F + D5 D0A5 ; # capital KH + D6 D0A6 ; # capital TS + D7 D0A7 ; # capital CH + D8 D0A8 ; # capital SH + D9 D0A9 ; # capital SHCH + DA D0AA ; # capital hard sign + DB D0AB ; # capital Y + DC D0AC ; # capital soft sign + DD D0AD ; # capital E + DE D0AE ; # capital YU + DF D0AF ; # capital YA + + E0 D0B0 ; # small a + E1 D0B1 ; # small b + E2 D0B2 ; # small v + E3 D0B3 ; # small g + E4 D0B4 ; # small d + E5 D0B5 ; # small ye + E6 D0B6 ; # small zh + E7 D0B7 ; # small z + E8 D0B8 ; # small i + E9 D0B9 ; # small j + EA D0BA ; # small k + EB D0BB ; # small l + EC D0BC ; # small m + ED D0BD ; # small n + EE D0BE ; # small o + EF D0BF ; # small p + + F0 D180 ; # small r + F1 D181 ; # small s + F2 D182 ; # small t + F3 D183 ; # small u + F4 D184 ; # small f + F5 D185 ; # small kh + F6 D186 ; # small ts + F7 D187 ; # small ch + F8 D188 ; # small sh + F9 D189 ; # small shch + FA D18A ; # small hard sign + FB D18B ; # small y + FC D18C ; # small soft sign + FD D18D ; # small e + FE D18E ; # small yu + FF D18F ; # small ya +} diff --git a/service-plans/nginx/config/worker.include b/service-plans/nginx/config/worker.include new file mode 100644 index 0000000..6b5fb7a --- /dev/null +++ b/service-plans/nginx/config/worker.include @@ -0,0 +1,6 @@ +worker_processes {{cfg.worker_processes}}; +daemon off; + +events { + worker_connections {{cfg.events.worker_connections}}; +} \ No newline at end of file diff --git a/service-plans/nginx/default.toml b/service-plans/nginx/default.toml new file mode 100644 index 0000000..40272d8 --- /dev/null +++ b/service-plans/nginx/default.toml @@ -0,0 +1,41 @@ + # # #### # # # # # + ## # # # # ## # # # + # # # # # # # # ## + # # # # ### # # # # ## + # ## # # # # ## # # + # # #### # # # # # + # For help with NGINX Config Tuning, + # refer to: http://nginx.org/en/docs/http/ngx_http_core_module.html + + +#### General Configuration +# a config file to entirely replace the built-in nginx.conf template +config_path = false + +# worker_processes: Number of NGINX processes. Default = 1 +worker_processes = 4 + + + +#### Events Context Configuration +[events] +# worker_connections: Connections per Worker Process. Default = 1024 +worker_connections = 1024 + + +#### HTTP Context Configuration +[http] +# http.sendfile: Enable (on) or disable (off) Sendfile Support. Default = on +sendfile = "on" + +# http.tcp_nopush: Enable (on) or disable (off) use of TCP_NOPUSH or TCP_CORK socket option. Default = on +tcp_nopush = "on" + +# http.tcp_nodelay: Enable (on) or disable (off) use of the TCP_NODELAY option. Default = on +tcp_nodelay = "on" + +# http.keepalive_timeout: Timeout on client connection keepalive, in seconds. Default = 75 +keepalive_timeout = 60 + +[http.listen] +port = 80 diff --git a/service-plans/nginx/hooks/run b/service-plans/nginx/hooks/run new file mode 100644 index 0000000..a1bf958 --- /dev/null +++ b/service-plans/nginx/hooks/run @@ -0,0 +1,9 @@ +#!/bin/bash + +exec 2>&1 + +{{#if cfg.config_path~}} + exec nginx -c {{cfg.config_path}} +{{~else~}} + exec nginx -c {{pkg.svc_config_path}}/nginx.conf +{{~/if}} diff --git a/service-plans/nginx/plan.sh b/service-plans/nginx/plan.sh new file mode 100644 index 0000000..2970c0e --- /dev/null +++ b/service-plans/nginx/plan.sh @@ -0,0 +1,65 @@ +pkg_name=nginx +pkg_origin=core +pkg_version=1.11.10 +pkg_description="NGINX web server." +pkg_maintainer="The Habitat Maintainers " +pkg_license=('bsd') +pkg_source=https://nginx.org/download/nginx-${pkg_version}.tar.gz +pkg_upstream_url=https://nginx.org/ +pkg_shasum=778b3cabb07633f754cd9dee32fc8e22582bce22bfa407be76a806abd935533d +pkg_deps=(core/glibc core/libedit core/ncurses core/zlib core/bzip2 core/openssl core/pcre) +pkg_build_deps=(core/gcc core/make core/coreutils) +pkg_lib_dirs=(lib) +pkg_bin_dirs=(sbin) +pkg_include_dirs=(include) +pkg_svc_user="root" +pkg_exports=( + [port]=http.listen.port +) +pkg_exposes=(port) + +do_build() { + ./configure --prefix="$pkg_prefix" \ + --conf-path="$pkg_svc_config_path/nginx.conf" \ + --sbin-path="$pkg_prefix/bin/nginx" \ + --pid-path="$pkg_svc_var_path/nginx.pid" \ + --lock-path="$pkg_svc_var_path/nginx.lock" \ + --user=hab \ + --group=hab \ + --http-log-path=/dev/stdout \ + --error-log-path=stderr \ + --http-client-body-temp-path="$pkg_svc_var_path/client-body" \ + --http-proxy-temp-path="$pkg_svc_var_path/proxy" \ + --http-fastcgi-temp-path="$pkg_svc_var_path/fastcgi" \ + --http-scgi-temp-path="$pkg_svc_var_path/scgi" \ + --http-uwsgi-temp-path="$pkg_svc_var_path/uwsgi" \ + --with-ipv6 \ + --with-pcre \ + --with-pcre-jit \ + --with-file-aio \ + --with-stream=dynamic \ + --with-mail=dynamic \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_realip_module \ + --with-http_v2_module \ + --with-http_ssl_module \ + --with-http_stub_status_module \ + --with-http_addition_module \ + --with-http_degradation_module \ + --with-http_flv_module \ + --with-http_mp4_module \ + --with-http_secure_link_module \ + --with-http_sub_module \ + --with-http_slice_module \ + --with-cc-opt="$CFLAGS" \ + --with-ld-opt="$LDFLAGS" + + make +} + +do_install() { + make install + mkdir -p "$pkg_prefix/sbin" + cp "$HAB_CACHE_SRC_PATH/$pkg_dirname/objs/nginx" "$pkg_prefix/sbin" +} diff --git a/service-plans/php/plan.sh b/service-plans/php/plan.sh new file mode 100644 index 0000000..38b7c45 --- /dev/null +++ b/service-plans/php/plan.sh @@ -0,0 +1,99 @@ +pkg_name=php +pkg_distname=php +pkg_origin=emergence +pkg_version=7.1.4 +pkg_maintainer="The Habitat Maintainers " +pkg_license=('PHP-3.01') +pkg_upstream_url=http://php.net/ +pkg_description="PHP is a popular general-purpose scripting language that is especially suited to web development." +pkg_source=https://php.net/get/${pkg_distname}-${pkg_version}.tar.bz2/from/this/mirror +pkg_filename=${pkg_distname}-${pkg_version}.tar.bz2 +pkg_dirname=${pkg_distname}-${pkg_version} +pkg_shasum=39bf697836e2760b3a44ea322e9e5f1f5b1f07abeb0111f6495eff7538e25805 +pkg_deps=( + core/coreutils + core/curl + core/glibc + core/libxml2 + core/libjpeg-turbo + core/libpng + core/openssl + core/zlib +) +pkg_build_deps=( + core/autoconf + core/bison2 + core/gcc + core/make + core/re2c + core/readline +) +pkg_bin_dirs=(bin sbin) +pkg_lib_dirs=(lib) +pkg_include_dirs=(include) +pkg_interpreters=(bin/php) + +apcu_version=5.1.8 +apcu_source=https://github.com/krakjoe/apcu/archive/v${apcu_version}.tar.gz +apcu_filename=apcu-${apcu_version}.tar.gz +apcu_shasum=09848619674a0871053cabba3907d2aade395772d54464d3aee45f519e217128 +apcu_dirname=apcu-${apcu_version} + +do_download() { + do_default_download + + download_file $apcu_source $apcu_filename $apcu_shasum +} + +do_verify() { + do_default_verify + + verify_file $apcu_filename $apcu_shasum +} + +do_unpack() { + do_default_unpack + + unpack_file $apcu_filename + mv "$HAB_CACHE_SRC_PATH/$apcu_dirname" "$HAB_CACHE_SRC_PATH/$pkg_dirname/ext/apcu" +} + +do_build() { + rm aclocal.m4 + ./buildconf --force + + ./configure --prefix="$pkg_prefix" \ + --enable-exif \ + --enable-fpm \ + --with-fpm-user=hab \ + --with-fpm-group=hab \ + --with-readline="$(pkg_path_for readline)" \ + --with-gettext="$(pkg_path_for glibc)" \ + --enable-apcu \ + --enable-mbstring \ + --enable-opcache \ + --with-mysqli=mysqlnd \ + --with-pdo-mysql=mysqlnd \ + --with-curl="$(pkg_path_for curl)" \ + --with-gd \ + --with-jpeg-dir="$(pkg_path_for libjpeg-turbo)" \ + --with-libxml-dir="$(pkg_path_for libxml2)" \ + --with-openssl="$(pkg_path_for openssl)" \ + --with-png-dir="$(pkg_path_for libpng)" \ + --with-xmlrpc \ + --with-zlib="$(pkg_path_for zlib)" + make +} + +do_install() { + do_default_install + + # Modify PHP-FPM config so it will be able to run out of the box. To run a real + # PHP-FPM application you would want to supply your own config with + # --fpm-config . + mv "$pkg_prefix/etc/php-fpm.conf.default" "$pkg_prefix/etc/php-fpm.conf" +} + +do_check() { + make test +} diff --git a/service-plans/php5/plan.sh b/service-plans/php5/plan.sh new file mode 100644 index 0000000..b5579cc --- /dev/null +++ b/service-plans/php5/plan.sh @@ -0,0 +1,101 @@ +pkg_name=php5 +pkg_distname=php +pkg_origin=emergence +pkg_version=5.6.23 +pkg_maintainer="The Habitat Maintainers " +pkg_license=('PHP-3.01') +pkg_upstream_url=http://php.net/ +pkg_description="PHP is a popular general-purpose scripting language that is especially suited to web development." +pkg_source=https://php.net/get/${pkg_distname}-${pkg_version}.tar.bz2/from/this/mirror +pkg_filename=${pkg_distname}-${pkg_version}.tar.bz2 +pkg_dirname=${pkg_distname}-${pkg_version} +pkg_shasum=facd280896d277e6f7084b60839e693d4db68318bfc92085d3dc0251fd3558c7 +pkg_deps=( + core/coreutils + core/curl + core/glibc + core/libxml2 + core/libjpeg-turbo + core/libpng + core/openssl + core/zlib +) +pkg_build_deps=( + core/autoconf + core/bison2 + core/gcc + core/make + core/re2c + core/readline +) +pkg_bin_dirs=(bin sbin) +pkg_lib_dirs=(lib) +pkg_include_dirs=(include) +pkg_interpreters=(bin/php) + +apcu_version=4.0.11 +apcu_source=https://github.com/krakjoe/apcu/archive/v${apcu_version}.tar.gz +apcu_filename=apcu-${apcu_version}.tar.gz +apcu_shasum=bf1d78d4211c6fde6d29bfa71947999efe0ba0c50bdc99af3f646e080f74e3a4 +apcu_dirname=apcu-${apcu_version} + +do_download() { + do_default_download + + download_file $apcu_source $apcu_filename $apcu_shasum +} + +do_verify() { + do_default_verify + + verify_file $apcu_filename $apcu_shasum +} + +do_unpack() { + do_default_unpack + + unpack_file $apcu_filename + mv "$HAB_CACHE_SRC_PATH/$apcu_dirname" "$HAB_CACHE_SRC_PATH/$pkg_dirname/ext/apcu" +} + +do_build() { + rm aclocal.m4 + ./buildconf --force + + ./configure --prefix="$pkg_prefix" \ + --enable-exif \ + --enable-fpm \ + --with-fpm-user=hab \ + --with-fpm-group=hab \ + --with-readline="$(pkg_path_for readline)" \ + --with-gettext="$(pkg_path_for glibc)" \ + --enable-apcu \ + --enable-mbstring \ + --enable-opcache \ + --with-mysqli=mysqlnd \ + --with-pdo-mysql=mysqlnd \ + --with-curl="$(pkg_path_for curl)" \ + --with-gd \ + --with-jpeg-dir="$(pkg_path_for libjpeg-turbo)" \ + --with-libxml-dir="$(pkg_path_for libxml2)" \ + --with-openssl="$(pkg_path_for openssl)" \ + --with-png-dir="$(pkg_path_for libpng)" \ + --with-xmlrpc \ + --with-zlib="$(pkg_path_for zlib)" + make +} + +do_install() { + do_default_install + + # Modify PHP-FPM config so it will be able to run out of the box. To run a real + # PHP-FPM application you would want to supply your own config with + # --fpm-config . + mv "$pkg_prefix/etc/php-fpm.conf.default" "$pkg_prefix/etc/php-fpm.conf" + # Run as the hab user by default, as it's more likely to exist than nobody. + sed -i "s/nobody/hab/g" "$pkg_prefix/etc/php-fpm.conf" +} + +do_check() { + make test +}