[buildout] parts = monitor-base promises frontend-reload tasks.json publish-connection-parameter extends = ${monitor-template:rendered} eggs-directory = ${buildout:eggs-directory} develop-eggs-directory = ${buildout:develop-eggs-directory} offline = true [frontend-instance-password] recipe = slapos.cookbook:generate.password username = node bytes = 12 [frontend-instance-certificate] recipe = plone.recipe.command command = if [ ! -e $${:key-file} ] then ${openssl-output:openssl} req -x509 -nodes -days 3650 \ -subj "/C=AA/ST=X/L=X/O=Dis/CN=$${:common-name}" \ -newkey rsa:1024 -keyout $${:key-file} \ -out $${:cert-file} fi update-command = $${:command} key-file = $${directory:etc}/$${:_buildout_section_name_}.key cert-file = $${directory:etc}/$${:_buildout_section_name_}.crt common-name = $${frontend-instance-config:ip} location = $${:key-file} $${:cert-file} [frontend-instance-config] recipe = slapos.recipe.template:jinja2 rendered = $${directory:etc}/$${:_buildout_section_name_} template = inline: :$${:port} { bind $${:ip} tls $${frontend-instance-certificate:cert-file} $${frontend-instance-certificate:key-file} log stdout errors stderr gzip # because caddy does not support upgrade http2 to websocket # https://tools.ietf.org/html/rfc8441 tls { alpn http/1.1 } root $${directory:frontend-static} browse proxy / $${theia-instance:base-url} { except public $${favicon.ico:filename} } proxy /services $${theia-instance:base-url} { websocket } proxy /file-upload $${theia-instance:base-url} { websocket } basicauth $${frontend-instance-password:username} $${frontend-instance-password:passwd} { realm "Theia" / } } ip = $${instance-parameter:ipv6-random} hostname = [$${:ip}] port = 3001 [frontend-instance] recipe = slapos.cookbook:wrapper wrapper-path = $${directory:services}/$${:_buildout_section_name_} command-line = ${caddy:output} -conf $${frontend-instance-config:rendered} -pidfile $${:pidfile} ip = $${frontend-instance-config:ip} hostname = $${frontend-instance-config:hostname} port = $${frontend-instance-config:port} pidfile = $${directory:pidfiles}/$${:_buildout_section_name_}.pid url = https://$${:hostname}:$${:port}/ [frontend-reload] recipe = slapos.cookbook:wrapper wrapper-path = $${directory:services}/$${:_buildout_section_name_} command-line = ${bash:location}/bin/bash -c "kill -s USR1 $$(${coreutils:location}/bin/cat $${frontend-instance:pidfile}) \ && ${coreutils:location}/bin/sleep infinity" hash-files = $${frontend-instance-config:rendered} $${frontend-instance:wrapper-path} wait-for-files = $${frontend-instance:pidfile} [favicon.ico] # generate a pseudo random favicon, different for each instance name. recipe = slapos.recipe.build install = import hashlib, shutil buildout_offline = self.buildout['buildout']['offline'] self.buildout['buildout']['offline'] = 'false' try: gravatar_url = "https://www.gravatar.com/avatar/" + hashlib.md5( '''$${slap-configuration:root-instance-title}''' ).hexdigest() + "?s=256&d=retro" shutil.copy(self.download(gravatar_url), '''$${:location}''') except Exception: # Because installation should work offline, if we can't download a favicon, # just ignore this step. self.logger.exception("Error while downloading favicon, using empty one") open('''$${:location}''', 'w').close() finally: self.buildout['buildout']['offline'] = buildout_offline location = $${directory:frontend-static}/$${:filename} filename = $${:_buildout_section_name_} [tasks.json] recipe = slapos.recipe.template:jinja2 rendered = $${directory:dot-theia}/tasks.json template = inline: { // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ { "label": "slapos node software", "detail": "Build all software supplied to the node", "type": "shell", "command": "${buildout:bin-directory}/slapos", "args": [ "node", "software", // debug mode can be enabled by commenting out this line: // "--buildout-debug", "--all" ], "options": { "env": { "SLAPOS_CONFIGURATION": "$${slapos-standalone-activate:slapos-configuration}", "GIT_EXEC_PATH": "" } }, "group": { "kind": "build", "isDefault": true }, "problemMatcher": [] }, { "label": "slapos node instance", "detail": "Create all instances requested on the node", "type": "shell", "command": "${buildout:bin-directory}/slapos", "args": [ "node", "instance", // debug mode can be enabled by commenting out this line: // "--buildout-debug", "--all" ], "options": { "env": { "SLAPOS_CONFIGURATION": "$${slapos-standalone-activate:slapos-configuration}", "GIT_EXEC_PATH": "" } }, "problemMatcher": [], "group": { "kind": "build", "isDefault": true } } ] } [user] recipe = slapos.cookbook:userinfo [theia-instance] recipe = slapos.cookbook:wrapper wrapper-path = $${directory:services}/$${:_buildout_section_name_} command-line = env HOME=$${buildout:directory} LC_ALL=C.UTF-8 TMP=$${directory:tmp} THEIA_WEBVIEW_EXTERNAL_ENDPOINT='{{hostname}}' THEIA_SHELL=$${theia-shell:rendered} ${theia-wrapper:rendered} --hostname=$${:hostname} --port=$${:port} $${directory:project} ip = $${instance-parameter:ipv4-random} hostname = $${:ip} port = 3000 base-url = http://$${:hostname}:$${:port}/ hash-existing-files = ${yarn.lock:output} ${theia-wrapper:rendered} [theia-shell] recipe = slapos.recipe.template:jinja2 rendered = $${directory:bin}/$${:_buildout_section_name_} mode = 0700 template = inline: #!${python:location}/bin/python import sys import os args = sys.argv[1:] # when running interactively, activate slapos configuration and reset GIT_EXEC_PATH to workaround https://github.com/eclipse-theia/theia/issues/7555 if not args: args = ["-c", ". $${slapos-standalone-activate:rendered} && exec env GIT_EXEC_PATH= ${bash:location}/bin/bash", ] os.execv('${bash:location}/bin/bash', ['${bash:location}/bin/bash'] + args) [slapos-standalone-activate] recipe = slapos.recipe.template:jinja2 rendered = $${directory:bin}/$${:_buildout_section_name_} mode = 0700 # XXX maybe standalone slapos should provide an activate script like virtualenv is doing? template = inline:#!/bin/sh export PATH=${buildout:bin-directory}:$PATH ${slapos-standalone:script-path} \ $${directory:slapos} \ $${:ipv4} \ $${:ipv6} \ $${:port} \ $${slap-connection:server-url} \ $${slap-connection:computer-id} \ $${slap-connection:partition-id} \ --key='$${slap-connection:key-file}' \ --cert='$${slap-connection:cert-file}' export SLAPOS_CONFIGURATION=$${:slapos-configuration} export SLAPOS_CLIENT_CONFIGURATION=$SLAPOS_CONFIGURATION ipv4 = $${instance-parameter:ipv4-random} ipv6 = $${instance-parameter:ipv6-random} port = 4000 slapos-configuration = $${directory:slapos}/etc/slapos.cfg [promises] recipe = instance-promises = $${theia-listen-promise:name} $${frontend-listen-promise:name} $${apache-frontend-url-available-promise:name} [theia-listen-promise] <= monitor-promise-base module = check_port_listening name = $${:_buildout_section_name_}.py config-hostname= $${theia-instance:ip} config-port = $${theia-instance:port} [frontend-listen-promise] <= monitor-promise-base module = check_port_listening name = $${:_buildout_section_name_}.py config-hostname = $${frontend-instance:ip} config-port = $${frontend-instance:port} [apache-frontend-url-available-promise] <= monitor-promise-base module = check_url_available name = $${:_buildout_section_name_}.py config-url = $${apache-frontend:connection-secure_access} config-check-secure = 1 [apache-frontend] <= slap-connection recipe = slapos.cookbook:requestoptional name = Theia Frontend # XXX We have hardcoded SR URL here. software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg slave = true config-url = $${frontend-instance:url} config-https-only = true config-type = websocket config-websocket-path-list = /services /file-upload return = domain secure_access [publish-connection-parameter] recipe = slapos.cookbook:publish url = $${apache-frontend:connection-secure_access} username = $${frontend-instance-password:username} password = $${frontend-instance-password:passwd} [instance-parameter] recipe = slapos.cookbook:slapconfiguration computer = $${slap-connection:computer-id} partition = $${slap-connection:partition-id} url = $${slap-connection:server-url} key = $${slap-connection:key-file} cert = $${slap-connection:cert-file} [directory] recipe = slapos.cookbook:mkdirectory etc = $${buildout:directory}/etc var = $${buildout:directory}/var srv = $${buildout:directory}/srv bin = $${buildout:directory}/bin tmp = $${buildout:directory}/tmp dot-theia = $${buildout:directory}/.theia/ pidfiles = $${:var}/run services = $${:etc}/service project = $${:srv}/project slapos = $${:srv}/slapos frontend-static = $${:srv}/frontend-static frontend-static-public = $${:frontend-static}/public