#!/usr/bin/env python2.7 import cgi import json import os import SimpleHTTPServer import SocketServer import subprocess import sys import threading VERSION = 'v0.4.13' hostname = '' try: command = "bash -c '[[ $(dig +short $HOSTNAME) ]] && echo $HOSTNAME || wget -q -O - icanhazip.com'" hostname = subprocess.check_output(command, shell=True) if ':' in hostname: hostname = '' except subprocess.CalledProcessError: pass key_file = os.getenv('KEY_FILE', '/root/.ssh/authorized_keys') admin_keys = [] if os.path.isfile(key_file): try: command = "cat {0}".format(key_file) admin_keys = subprocess.check_output(command, shell=True).strip().split("\n") except subprocess.CalledProcessError: pass def check_boot(): if 'onboot' not in sys.argv: return init_dir = os.getenv('INIT_DIR', '/etc/init') systemd_dir = os.getenv('SYSTEMD_DIR', '/etc/systemd/system') nginx_dir = os.getenv('NGINX_DIR', '/etc/nginx/conf.d') if os.path.exists(init_dir): with open('{0}/dokku-installer.conf'.format(init_dir), 'w') as f: f.write("start on runlevel [2345]\n") f.write("exec {0} selfdestruct\n".format(os.path.abspath(__file__))) if os.path.exists(systemd_dir): with open('{0}/dokku-installer.service'.format(systemd_dir), 'w') as f: f.write("[Unit]\n") f.write("Description=Dokku web-installer\n") f.write("\n") f.write("[Service]\n") f.write("ExecStart={0} selfdestruct\n".format(os.path.abspath(__file__))) f.write("\n") f.write("[Install]\n") f.write("WantedBy=multi-user.target\n") f.write("WantedBy=graphical.target\n") if os.path.exists(nginx_dir): with open('{0}/dokku-installer.conf'.format(nginx_dir), 'w') as f: f.write("upstream dokku-installer { server 127.0.0.1:2000; }\n") f.write("server {\n") f.write(" listen 80;\n") f.write(" location / {\n") f.write(" proxy_pass http://dokku-installer;\n") f.write(" }\n") f.write("}\n") subprocess.call('rm -f /etc/nginx/sites-enabled/*', shell=True) sys.exit(0) class GetHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): def do_GET(self): content = PAGE.replace('{VERSION}', VERSION) content = content.replace('{HOSTNAME}', hostname) content = content.replace('{ADMIN_KEYS}', "\n".join(admin_keys)) self.send_response(200) self.end_headers() self.wfile.write(content) def do_POST(self): if self.path not in ['/setup', '/setup/']: return params = cgi.FieldStorage(fp=self.rfile, headers=self.headers, environ={ 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': self.headers['Content-Type']}) dokku_root = os.getenv('DOKKU_ROOT', '/home/dokku') if 'vhost' in params and params['vhost'].value == 'true': with open('{0}/VHOST'.format(dokku_root), 'w') as f: f.write(params['hostname'].value) else: try: os.remove('{0}/VHOST'.format(dokku_root)) except OSError: pass with open('{0}/HOSTNAME'.format(dokku_root), 'w') as f: f.write(params['hostname'].value) command = ['sshcommand', 'acl-add', 'dokku', 'admin'] for key in params['keys'].value.split("\n"): proc = subprocess.Popen(command, stdin=subprocess.PIPE) proc.stdin.write(key) proc.stdin.close() proc.wait() if 'selfdestruct' in sys.argv: DeleteInstallerThread() self.send_response(200) self.end_headers() self.wfile.write(json.dumps({'status': 'ok'})) class DeleteInstallerThread(object): def __init__(self, interval=1): thread = threading.Thread(target=self.run, args=()) thread.daemon = True thread.start() def run(self): command = "rm /etc/nginx/conf.d/dokku-installer.conf && /etc/init.d/nginx stop && /etc/init.d/nginx start" try: subprocess.call(command, shell=True) except: pass command = "rm -f /etc/init/dokku-installer.conf /etc/systemd/system/dokku-installer.service && stop dokku-installer" try: subprocess.call(command, shell=True) except: pass def main(): check_boot() port = int(os.getenv('PORT', 2000)) httpd = SocketServer.TCPServer(("", port), GetHandler) print "Listening on 0.0.0.0:{0}, CTRL+C to stop".format(port) httpd.serve_forever() PAGE = """