diff --git a/README.md b/README.md index 378a0d8..fb38413 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,12 @@ walnut Small, light, and secure iot application framework. +```bash +curl https://git.daplie.com/Daplie/daplie-snippets/raw/master/install.sh | bash + +daplie-install-cloud +``` + Features ------ diff --git a/dist/Library/LaunchDaemons/com.daplie.walnut.web.plist b/dist/Library/LaunchDaemons/com.daplie.walnut.web.plist new file mode 100644 index 0000000..4c9a382 --- /dev/null +++ b/dist/Library/LaunchDaemons/com.daplie.walnut.web.plist @@ -0,0 +1,52 @@ + + + + + Label + WALNUT + ProgramArguments + + /usr/local/bin/walnut + --config + /etc/walnut/walnut.yml + + EnvironmentVariables + + WALNUT_PATH + /opt/walnut + + + UserName + root + GroupName + wheel + InitGroups + + + RunAtLoad + + KeepAlive + + Crashed + + SuccessfulExit + + + + SoftResourceLimits + + NumberOfFiles + 8192 + + HardResourceLimits + + + WorkingDirectory + /srv/www + + StandardErrorPath + /var/log/walnut/error.log + StandardOutPath + /var/log/walnut/info.log + + diff --git a/dist/etc/systemd/system/walnut.service b/dist/etc/systemd/system/walnut.service new file mode 100644 index 0000000..061e113 --- /dev/null +++ b/dist/etc/systemd/system/walnut.service @@ -0,0 +1,68 @@ +[Unit] +Description=WALNUT IoT App Infrastructure +Documentation=https://git.daplie.com/Daplie/walnut.js +After=network-online.target +Wants=network-online.target systemd-networkd-wait-online.service + +[Service] +# Restart on crash (bad signal), and on 'clean' failure (error exit code) +# Allow up to 3 restarts within 10 seconds +# (it's unlikely that a user or properly-running script will do this) +Restart=on-failure +StartLimitInterval=10 +StartLimitBurst=3 + +# The v8 VM will output a "clean" for JavaScript errors. +# If we knew we were never going to accidentally exit cleanly +# we would use on-abnormal: +; Restart=on-abnormal + +# User and group the process will run as +# (www-data is the de facto standard on most systems) +User=www-data +Group=www-data + +# If we need to pass environment variables in the future +; Environment=GOLDILOCKS_PATH=/opt/walnut + +# Set a sane working directory, sane flags, and specify how to reload the config file +WorkingDirectory=/srv/www +ExecStart=/usr/local/bin/walnut --config=/etc/walnut/walnut.yml +ExecReload=/bin/kill -USR1 $MAINPID + +# Limit the number of file descriptors and processes; see `man systemd.exec` for more limit settings. +# We don't expected to use more than this. +LimitNOFILE=1048576 +LimitNPROC=64 + +# Use private /tmp and /var/tmp, which are discarded after the process stops. +PrivateTmp=true +# Use a minimal /dev +PrivateDevices=true +# Hide /home, /root, and /run/user. Nobody will steal your SSH-keys. +ProtectHome=true +# Make /usr, /boot, /etc and possibly some more folders read-only. +ProtectSystem=full +# … except TLS/SSL, ACME, and Let's Encrypt certificates +# and /var/log/, because we want a place where logs can go. +# This merely retains r/w access rights, it does not add any new. Must still be writable on the host! +ReadWriteDirectories=/etc/walnut /etc/acme /etc/letsencrypt /etc/ssl /var/log/walnut /var/walnut /opt/walnut /srv/www + +# Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories +; ReadWritePaths=/etc/walnut /var/log/walnut +; +# The following additional security directives only work with systemd v229 or later. +# They further retrict privileges that can be gained. +# Note that you may have to add capabilities required by any plugins in use. +CapabilityBoundingSet=CAP_NET_BIND_SERVICE +AmbientCapabilities=CAP_NET_BIND_SERVICE +NoNewPrivileges=true + +# Caveat: Some plugins need additional capabilities. +# For example "upload" needs CAP_LEASE +; CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_LEASE +; AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_LEASE +; NoNewPrivileges=true + +[Install] +WantedBy=multi-user.target diff --git a/dist/etc/tmpfiles.d/walnut.conf b/dist/etc/tmpfiles.d/walnut.conf new file mode 100644 index 0000000..3f16a3d --- /dev/null +++ b/dist/etc/tmpfiles.d/walnut.conf @@ -0,0 +1,12 @@ +# /etc/tmpfiles.d/walnut.conf +# See https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html + +# Type Path Mode UID GID Age Argument +d /etc/walnut 0755 www-data www-data - - +d /etc/ssl/walnut 0750 www-data www-data - - +d /srv/walnut 0775 www-data www-data - - +d /srv/www 0775 www-data www-data - - +d /opt/walnut 0775 www-data www-data - - +d /var/walnut 0775 www-data www-data - - +d /var/log/walnut 0750 www-data www-data - - +#d /run/walnut 0755 www-data www-data - - diff --git a/install.sh b/install.sh index e8f78d4..622ac71 100755 --- a/install.sh +++ b/install.sh @@ -3,21 +3,20 @@ echo "no install yet" exit 1 -sudo mkdir -p /srv/walnut/{certs,core,letsencrypt,lib,etc,config} +sudo mkdir -p /srv/walnut/{core,lib,etc,config,node_modules} +ln -sf ../node_modules /srv/walnut/core/node_modules sudo mkdir -p /srv/walnut/etc/org.oauth3.consumer sudo mkdir -p /srv/walnut/etc/org.oauth3.provider sudo mkdir -p /srv/walnut/packages/{api,pages,services} sudo chown -R $(whoami):$(whoami) /srv/walnut -#git clone git@github.com:Daplie/walnut.git -git clone https://github.com/Daplie/walnut.git /srv/walnut/core +#git clone git@git.daplie.com:Daplie/walnut.js.git +#git clone https://git.daplie.com/Daplie/walnut.js.git /srv/walnut/core pushd /srv/walnut/core npm install popd -sudo rsync -a /srv/walnut/core/etc/init/walnut.conf /etc/init/walnut.conf -rsync -a /srv/walnut/core/etc/letsencrypt/ /srv/walnut/certs/ mv /srv/walnut/core/node_modules /srv/walnut echo -n "Enter an email address to use for LetsEncrypt and press [ENTER]: " @@ -32,5 +31,169 @@ node -e " }, null, ' ')); " -sudo service walnut stop -sudo service walnut start +############################### +# # +# http_get # +# boilerplate for curl / wget # +# # +############################### + +# See https://git.daplie.com/Daplie/daplie-snippets/blob/master/bash/http-get.sh + +http_curl_opts="-fsSL" +http_wget_opts="--quiet" + +http_bin="" +http_opts="" +http_out="" + +detect_http_bin() +{ + if type -p curl >/dev/null 2>&1; then + http_bin="curl" + http_opts="$http_curl_opts" + http_out="-o" + #curl -fsSL "$url" -o "$PREFIX/tmp/$pkg" + elif type -p wget >/dev/null 2>&1; then + http_bin="wget" + http_opts="$http_wget_opts" + http_out="-O" + #wget --quiet "$url" -O "$PREFIX/tmp/$pkg" + else + echo "Aborted, could not find curl or wget" + return 7 + fi +} + +http_get() +{ + if [ -e "$2" ]; then + rsync -a "$2" "$1" + elif type -p curl >/dev/null 2>&1; then + $http_bin $http_curl_opts $http_out "$2" "$1" + elif type -p wget >/dev/null 2>&1; then + $http_bin $http_wget_opts $http_out "$2" "$1" + else + echo "Aborted, could not find curl or wget" + return 7 + fi +} + +dap_dl() +{ + $http_bin $http_opts $http_out "$2" "$1" +} + +dap_dl_bash() +{ + dap_url=$1 + #dap_args=$2 + rm -rf dap-tmp-runner.sh + $http_bin $http_opts $http_out dap-tmp-runner.sh "$dap_url"; bash dap-tmp-runner.sh; rm dap-tmp-runner.sh +} + +detect_http_bin + +## END HTTP_GET ## + +################################# +# # +# linux and osx system services # +# # +################################# + +# Use $PREFIX for compatibility with Termux on Android + +# Not every platform has or needs sudo +sudo_cmd="" +((EUID)) && [[ -z "$ANDROID_ROOT" ]] && sudo_cmd="sudo" + +my_app_name=goldilocks +my_app_pkg_name=com.daplie.goldilocks.web +my_app_dir=$(mktemp -d) +installer_base="https://git.daplie.com/Daplie/goldilocks.js/raw/master" # add "/dist" as needed + +my_app_systemd_service="etc/systemd/system/${my_app_name}.service" +my_app_systemd_tmpfiles="etc/tmpfiles.d/${my_app_name}.conf" +my_app_launchd_service="Library/LaunchDaemons/${my_app_pkg_name}.plist" +my_app_upstart_service="etc/init/${my_app_pkg_name}.conf" + +install_for_systemd() +{ + echo "" + echo "Installing as systemd service" + echo "" + + dap_dl "$installer_base/$my_app_system_service" "$my_app_dir/$my_app_system_service" + $sudo_cmd mv "$my_app_dir/$my_app_system_service" "$PREFIX/$my_app_system_service" + $sudo_cmd chown -R root:root "$PREFIX/$my_app_system_service" + $sudo_cmd chmod 644 "$PREFIX/$my_app_system_service" + + dap_dl "$installer_base/$my_app_system_tmpfiles" "$my_app_dir/$my_app_system_tmpfiles" + $sudo_cmd mv "$my_app_dir/$my_app_system_tmpfiles" "$PREFIX/$my_app_system_tmpfiles" + $sudo_cmd chown -R root:root "$PREFIX/$my_app_system_tmpfiles" + $sudo_cmd chmod 644 "$PREFIX/$my_app_system_tmpfiles" + + $sudo_cmd systemctl stop "${my_app_name}.service" >/dev/null 2>/dev/null + $sudo_cmd systemctl daemon-reload + $sudo_cmd systemctl start "${my_app_name}.service" + $sudo_cmd systemctl enable "${my_app_name}.service" + + echo "$my_app_name started with systemctl" +} + +install_for_launchd() +{ + echo "" + echo "Installing as launchd service" + echo "" + + # See http://www.launchd.info/ + dap_dl "$installer_base/$my_app_launchd_service" "$my_app_dir/$my_app_launchd_service" + $sudo_cmd mv "$my_app_dir/$my_app_launchd_service" "$PREFIX/$my_app_launchd_service" + $sudo_cmd chown root:wheel "$PREFIX/$my_app_launchd_service" + $sudo_cmd chmod 0644 "$PREFIX/$my_app_launchd_service" + $sudo_cmd launchctl unload -w "$PREFIX/$my_app_launchd_service" >/dev/null 2>/dev/null + $sudo_cmd launchctl load -w "$PREFIX/$my_app_launchd_service" + + echo "$my_app_name started with launchd" +} + +install_for_upstart() +{ + echo "" + echo "Installing as upstart service" + echo "" + + dap_dl "$installer_base/$my_app_upstart_service" "$my_app_dir/$my_app_upstart_service" + $sudo_cmd mv "$my_app_dir/$my_app_upstart_service" "$PREFIX/$my_app_upstart_service" + $sudo_cmd chown root:wheel "$PREFIX/$my_app_upstart_service" + $sudo_cmd chmod 0644 "$PREFIX/$my_app_upstart_service" + + echo "$my_app_name started with upstart" +} + +install_service() +{ + installable="" + if [ -d "$PREFIX/etc/systemd/system" ]; then + install_for_systemd + installable="true" + fi + if [ -d "/Library/LaunchDaemons" ]; then + install_for_launchd + installable="true" + fi + if [ -d "$PREFIX/etc/init" ]; then + install_for_upstart + installable="true" + fi + if [ -z "$installable" ]; then + echo "" + echo "Unknown system service init type. You must install as a system service manually." + echo '(please file a bug with the output of "uname -a")' + echo "" + fi +} + +install_service