├── .gitignore ├── tests ├── apps │ ├── .go.disabled │ │ ├── .godir │ │ ├── Procfile │ │ ├── check_deploy │ │ └── web.go │ ├── nodejs-express │ │ ├── Procfile │ │ ├── check_deploy │ │ ├── package.json │ │ └── web.js │ ├── python-flask │ │ ├── Procfile │ │ ├── requirements.txt │ │ ├── check_deploy │ │ └── hello.py │ └── php │ │ ├── index.php │ │ └── check_deploy ├── setup_travis ├── test_deploy ├── run_vagrant └── run_ec2 ├── .gitmodules ├── nginx-reloader.conf ├── HISTORY.md ├── nginx-app-conf ├── ROADMAP.md ├── receiver ├── dokku ├── AUTHORS ├── .travis.yml ├── Vagrantfile ├── deploystep ├── LICENSE ├── Makefile ├── .s3cfg ├── bootstrap.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | -------------------------------------------------------------------------------- /tests/apps/.go.disabled/.godir: -------------------------------------------------------------------------------- 1 | go 2 | -------------------------------------------------------------------------------- /tests/apps/.go.disabled/Procfile: -------------------------------------------------------------------------------- 1 | web: go 2 | -------------------------------------------------------------------------------- /tests/apps/nodejs-express/Procfile: -------------------------------------------------------------------------------- 1 | web: bin/node web.js 2 | -------------------------------------------------------------------------------- /tests/apps/python-flask/Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn hello:app 2 | -------------------------------------------------------------------------------- /tests/apps/php/index.php: -------------------------------------------------------------------------------- 1 | php'; ?> 2 | -------------------------------------------------------------------------------- /tests/apps/.go.disabled/check_deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e; test "$(curl -s $1)" == "go" -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "buildstep"] 2 | path = buildstep 3 | url = https://github.com/progrium/buildstep.git 4 | -------------------------------------------------------------------------------- /tests/apps/python-flask/requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==0.9 2 | Jinja2==2.6 3 | Werkzeug==0.8.3 4 | gunicorn==0.17.2 5 | 6 | -------------------------------------------------------------------------------- /tests/apps/python-flask/check_deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e; output="$(curl -s $1)"; echo $output; test "$output" == "python/flask" -------------------------------------------------------------------------------- /nginx-reloader.conf: -------------------------------------------------------------------------------- 1 | script 2 | echo | sudo -u git nc -l -U /home/git/reload-nginx && /etc/init.d/nginx reload 3 | end script 4 | respawn -------------------------------------------------------------------------------- /tests/apps/nodejs-express/check_deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e; output="$(curl -s $1)"; echo $output; test "$output" == "nodejs/express" -------------------------------------------------------------------------------- /tests/apps/php/check_deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e; output="$(curl -s $1)"; echo $output; test "$output" == "

php

" -------------------------------------------------------------------------------- /tests/apps/python-flask/hello.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask import Flask 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route('/') 7 | def hello(): 8 | return 'python/flask' 9 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | # History 2 | 3 | ## 0.1.0 (2013-06-15) 4 | 5 | * First release 6 | * Bootstrap script for Ubuntu system 7 | * Basic push / deploy with git 8 | * Hostname support with Nginx 9 | * Support for Java, Ruby, Node.js buildpacks -------------------------------------------------------------------------------- /tests/apps/nodejs-express/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-example", 3 | "version": "0.0.1", 4 | "dependencies": { 5 | "express": "2.5.x" 6 | }, 7 | "engines": { 8 | "node": "0.8.x", 9 | "npm": "1.1.x" 10 | } 11 | } -------------------------------------------------------------------------------- /nginx-app-conf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | APP="$1"; PORT="$2"; HOSTNAME="$3" 3 | cat< Building $APP ..." 7 | cat | $HOME/buildstep $CONTAINER 8 | echo "-----> Build complete!" 9 | 10 | echo "-----> Deploying $APP ..." 11 | $HOME/deploystep $APP $CONTAINER 12 | echo "-----> Application deployed:" 13 | echo " http://$(< "$HOME/$APP/HOSTNAME")" 14 | echo -------------------------------------------------------------------------------- /dokku: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | case "$1" in 3 | logs) 4 | CONTAINER=$( ~/.ssh/id_rsa.pub -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This file lists all individuals having contributed content to the repository. 2 | # If you're submitting a patch, please add your name here in alphabetical order as part of the patch. 3 | # 4 | Felipe Coury 5 | Jeff Lindsay 6 | rhy-jot 7 | Richard North 8 | Leo Unbekandt 9 | Martin Weiss 10 | Silas Baronda 11 | -------------------------------------------------------------------------------- /tests/test_deploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | SELF=`which $0`; APP="$1"; TARGET="$2" 4 | TMP=$(mktemp -d -t "$TARGET.XXXXX") 5 | trap "rm -rf $TMP" EXIT 6 | rmdir $TMP && cp -r $(dirname $SELF)/$APP $TMP 7 | cd $TMP 8 | git init 9 | git config user.email "robot@example.com" 10 | git config user.name "Test Robot" 11 | git add . 12 | git commit -m 'initial commit' 13 | REPO="test-$(basename $APP)-$RANDOM" 14 | git remote add target git@$TARGET:$REPO 15 | git push target master 16 | ./check_deploy "$(ssh dokku@$TARGET url $REPO)" && echo "-----> Deploy success!" -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | script: cd tests && ./run_ec2 test 3 | before_install: 4 | - "sudo apt-get install -y ec2-api-tools" 5 | - "sudo apt-get install -y s3cmd" 6 | - "tests/setup_travis" 7 | env: 8 | global: 9 | - EC2_CERT=/tmp/cert 10 | - EC2_PRIVATE_KEY=/tmp/pk 11 | - secure: "flDyaNZ6Xn2W1JyI3N1DCzI+K7ACgAZJ38vVfSde6rmI/V2iaAR4YH+7PC/x\nb/uCW9JCl+IVq5DJ0vu59HkAXlV4i4S9gVDExygt/fAo+sfGiMWubRUZMZeC\nHKK+92kexmqGRJLU8s5wDakddMAZ4+y7QPfVdxAHp/Tuijq+9iE=" 12 | - secure: "gSYrtzzmbwumE60J9sUhIaA5vakfXnP4NtCbxha0pyepPFrlds3YO0lxoH7J\nYdG8Yl5ObdqyDNQ2Yb/FL7wmctuPZSZ3OHQNjDpOqsqOqr7M2+b8aVM8URKE\n/Lki+GP8M8kajBr6zKgIV1W+e8SZQsAazhHwKRaJJQVWT58Aghk=" 13 | -------------------------------------------------------------------------------- /tests/run_vagrant: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SELF=`which $0` 3 | VAGRANT_SSH_PORT=${$VAGRANT_SSH_PORT:-"2222"} 4 | PUBLIC_KEY=${PUBLIC_KEY:-"~/.ssh/id_rsa.pub"} 5 | indent() { sed "s/^/ /"; } 6 | if [[ ! $(cat ~/.ssh/config 2>/dev/null | grep dokku.me) ]]; then 7 | echo "-----> Configuring SSH to use $VAGRANT_SSH_PORT for dokku.me..." 8 | touch ~/.ssh/config 9 | echo "Host dokku.me" >> ~/.ssh/config 10 | echo " Port $VAGRANT_SSH_PORT" >> ~/.ssh/config 11 | fi 12 | echo "-----> Ensuring Vagrant is running..." 13 | cd "$(dirname $SELF)/.." && vagrant up | indent 14 | cat $PUBLIC_KEY | ssh -o "StrictHostKeyChecking=no" -i ~/.vagrant.d/insecure_private_key vagrant@dokku.me "sudo gitreceive upload-key test" 15 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | BOX_NAME = ENV["BOX_NAME"] || "raring" 5 | BOX_URI = ENV["BOX_URI"] || "https://cloud-images.ubuntu.com/vagrant/raring/current/raring-server-cloudimg-amd64-vagrant-disk1.box" 6 | DOKKU_DOMAIN = ENV["DOKKU_DOMAIN"] || "dokku.me" 7 | DOKKU_IP = ENV["DOKKU_IP"] || "10.0.0.2" 8 | 9 | Vagrant::configure("2") do |config| 10 | config.vm.box = BOX_NAME 11 | config.vm.box_url = BOX_URI 12 | config.vm.provision :shell, :path => "bootstrap.sh" 13 | config.vm.network :forwarded_port, guest: 80, host: 8080 14 | config.vm.hostname = "#{DOKKU_DOMAIN}" 15 | config.vm.network :private_network, ip: DOKKU_IP 16 | 17 | config.vm.provider :virtualbox do |vb| 18 | vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"] 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /deploystep: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | APP="$1"; CONTAINER="$2" 3 | 4 | if [[ ! -f "$HOME/$APP/PORT" ]]; then 5 | # First deploy 6 | ID=$(docker run -d -p 5000 -e PORT=5000 $CONTAINER /bin/bash -c "/start web") 7 | echo $ID > "$HOME/$APP/CONTAINER" 8 | PORT=$(docker port $ID 5000) 9 | echo $PORT > "$HOME/$APP/PORT" 10 | if [[ -f "$HOME/DOMAIN" ]]; then 11 | HOSTNAME="${APP/\//-}.$(< "$HOME/DOMAIN")" 12 | $HOME/nginx-app-conf ${APP/\//-} $PORT $HOSTNAME > $HOME/$APP/nginx.conf 13 | nc -U $HOME/reload-nginx 14 | else 15 | HOSTNAME="$(< "$HOME/HOSTNAME"):$PORT" 16 | fi 17 | echo $HOSTNAME > "$HOME/$APP/HOSTNAME" 18 | else 19 | # Regular deploy 20 | OLDID=$(< "$HOME/$APP/CONTAINER") 21 | docker kill $OLDID > /dev/null 22 | PORT=$(< "$HOME/$APP/PORT") 23 | ID=$(docker run -d -p ":$PORT" -e "PORT=$PORT" $CONTAINER /bin/bash -c "/start web") 24 | echo $ID > "$HOME/$APP/CONTAINER" 25 | fi 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 Jeff Lindsay 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GITRECEIVE_URL = https://raw.github.com/progrium/gitreceive/master/gitreceive 2 | SSHCOMMAND_URL = https://raw.github.com/progrium/sshcommand/master/sshcommand 3 | 4 | all: install 5 | 6 | install: submodule gitreceive sshcommand 7 | cp dokku /usr/local/bin/dokku 8 | cp receiver /home/git/receiver 9 | cp deploystep /home/git/deploystep 10 | cp buildstep/buildstep /home/git/buildstep 11 | cp nginx-app-conf /home/git/nginx-app-conf 12 | cp nginx-reloader.conf /etc/init/nginx-reloader.conf 13 | echo "include /home/git/*/nginx.conf;" > /etc/nginx/conf.d/dokku.conf 14 | 15 | submodule: 16 | git submodule init 17 | git submodule update 18 | 19 | gitreceive: 20 | wget -qO /usr/local/bin/gitreceive ${GITRECEIVE_URL} 21 | chmod +x /usr/local/bin/gitreceive 22 | gitreceive init 23 | 24 | sshcommand: 25 | wget -qO /usr/local/bin/sshcommand ${SSHCOMMAND_URL} 26 | chmod +x /usr/local/bin/sshcommand 27 | sshcommand create dokku /usr/local/bin/dokku 28 | 29 | count: 30 | cat receiver deploystep bootstrap.sh nginx-app-conf nginx-reloader.conf | wc -l -------------------------------------------------------------------------------- /.s3cfg: -------------------------------------------------------------------------------- 1 | [default] 2 | access_key 3 | secret_key 4 | bucket_location = US 5 | cloudfront_host = cloudfront.amazonaws.com 6 | cloudfront_resource = /2010-07-15/distribution 7 | default_mime_type = binary/octet-stream 8 | delete_removed = False 9 | dry_run = False 10 | encoding = UTF-8 11 | encrypt = False 12 | follow_symlinks = False 13 | force = False 14 | get_continue = False 15 | gpg_command = None 16 | gpg_decrypt = %(gpg_command)s -d --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s 17 | gpg_encrypt = %(gpg_command)s -c --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s 18 | gpg_passphrase = 19 | guess_mime_type = True 20 | host_base = s3.amazonaws.com 21 | host_bucket = %(bucket)s.s3.amazonaws.com 22 | human_readable_sizes = False 23 | list_md5 = False 24 | log_target_prefix = 25 | preserve_attrs = True 26 | progress_meter = True 27 | proxy_host = 28 | proxy_port = 0 29 | recursive = False 30 | recv_chunk = 4096 31 | reduced_redundancy = False 32 | send_chunk = 4096 33 | simpledb_host = sdb.amazonaws.com 34 | skip_existing = False 35 | socket_timeout = 300 36 | urlencoding_mode = normal 37 | use_https = False 38 | verbosity = WARNING 39 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | DOKKU_REPO=${DOKKU_REPO:-"https://github.com/progrium/dokku.git"} 2 | DOKKU_STACK=${DOKKU_STACK:-"https://s3.amazonaws.com/progrium-dokku/progrium_buildstep.tgz"} 3 | DOCKER_PKG=${DOCKER_PKG:-"https://launchpad.net/~dotcloud/+archive/lxc-docker/+files/lxc-docker_0.4.2-1_amd64.deb"} 4 | set -e 5 | 6 | apt-get update 7 | DEBIAN_FRONTEND=noninteractive apt-get install -y linux-image-extra-`uname -r` 8 | apt-get install -y git nginx make curl dnsutils 9 | 10 | wget -qO- "$DOCKER_PKG" > /tmp/lxc-docker_0.4.2-1_amd64.deb 11 | dpkg --force-depends -i /tmp/lxc-docker_0.4.2-1_amd64.deb && apt-get install -f -y 12 | rm /tmp/lxc-docker_0.4.2-1_amd64.deb 13 | 14 | sed -i.bak 's/docker -d/docker -d -r=true/' /etc/init/docker.conf # Docker should restart containers 15 | 16 | cd ~ && git clone ${DOKKU_REPO} 17 | cd dokku && make install 18 | if [[ $DOKKU_STACK ]]; then 19 | curl "$DOKKU_STACK" | gunzip -cd | docker import - progrium/buildstep 20 | else 21 | cd buildstep && make build 22 | fi 23 | 24 | [[ -f /etc/nginx/nginx.conf ]] && sed -i 's/# server_names_hash_bucket_size/server_names_hash_bucket_size/' /etc/nginx/nginx.conf 25 | 26 | /etc/init.d/nginx start 27 | start nginx-reloader 28 | 29 | [[ $(dig +short $HOSTNAME) ]] && HOSTFILE=DOMAIN || HOSTFILE=HOSTNAME 30 | echo $HOSTNAME > /home/git/$HOSTFILE 31 | 32 | echo 33 | echo "Be sure to upload a public key for your user:" 34 | echo " cat ~/.ssh/id_rsa.pub | ssh root@$HOSTNAME \"gitreceive upload-key progrium\"" 35 | -------------------------------------------------------------------------------- /tests/run_ec2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | KEYNAME="$1" 3 | indent() { sed "s/^/ /"; } 4 | echo "-----> Booting EC2 instance..." 5 | start=$(ec2-run-instances -k $1 ami-f3d1bb9a 2>&1 ) 6 | if [[ $? > 0 ]]; then 7 | echo "$start" | indent 8 | exit 3 9 | fi 10 | INSTANCE=$(echo "$start" | awk '/^INSTANCE/ {print $2}') 11 | terminate() { 12 | echo "-----> Terminating $INSTANCE..." 13 | ec2-terminate-instances $INSTANCE &>/dev/null && echo " Shutting down" 14 | } 15 | [[ $NOCLEANUP ]] || trap "terminate" EXIT 16 | sleep 30 17 | status="" 18 | while [[ "$status" != "running" ]]; do 19 | info=$(ec2-describe-instances 2>/dev/null | grep $INSTANCE) 20 | status=$(echo "$info" | cut -f 6 | grep run) 21 | echo " Waiting..." 22 | sleep 5 23 | if [[ $status == "running" ]]; then 24 | echo "-----> $INSTANCE has succesfully booted!" 25 | break 26 | fi 27 | done 28 | PUBLIC_IP=$(echo "$info" | awk '{print $14}') 29 | echo "-----> Waiting for SSH at $PUBLIC_IP..." 30 | while [[ ! $(echo | nc $PUBLIC_IP 22) ]]; do 31 | sleep 5 32 | echo " Waiting..." 33 | done 34 | set -e 35 | echo "-----> Connecting and running boostrap script..." 36 | cat ../bootstrap.sh | ssh -o "StrictHostKeyChecking=no" ubuntu@$PUBLIC_IP "HOSTNAME=$PUBLIC_IP sudo bash" 2>&1 | indent 37 | echo "-----> Installing SSH public keys..." 38 | cat ~/.ssh/id_rsa.pub | ssh -o "StrictHostKeyChecking=no" ubuntu@$PUBLIC_IP "sudo gitreceive upload-key test" > /dev/null 39 | cat ~/.ssh/id_rsa.pub | ssh -o "StrictHostKeyChecking=no" ubuntu@$PUBLIC_IP "sudo sshcommand acl-add dokku test" > /dev/null 40 | for app_path in apps/*; do 41 | app=$(basename $app_path) 42 | echo "-----> Running test deploy of $app..." 43 | ./test_deploy $app_path $PUBLIC_IP 44 | done -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dokku 2 | 3 | Docker powered mini-Heroku. The smallest PaaS implementation you've ever seen. 4 | 5 | ## Requirements 6 | 7 | Assumes Ubuntu 13 right now. Ideally have a domain ready to point to your host. It's designed for and is probably 8 | best to use a fresh VM. The bootstrapper will install everything it needs. 9 | 10 | ## Installing 11 | 12 | $ wget -qO- https://raw.github.com/progrium/dokku/master/bootstrap.sh | sudo bash 13 | 14 | This may take around 5 minutes. Certainly better than the several hours it takes to bootstrap Cloud Foundry. 15 | 16 | ## Configuring 17 | 18 | Set up a domain and a wildcard domain pointing to that host. Make sure `/home/git/DOMAIN` is set to this domain. 19 | By default it's set to whatever the hostname the host has. 20 | 21 | You'll have to add a public key associated with a username as it says at the end of the bootstrapper. You'll do something 22 | like this from your local machine: 23 | 24 | $ cat ~/.ssh/id_rsa.pub | ssh progriumapp.com "sudo gitreceive upload-key progrium" 25 | 26 | That's it! 27 | 28 | ## Deploy an App 29 | 30 | Right now Buildstep supports buildpacks for Node.js, Ruby, Python, [and more](https://github.com/progrium/buildstep#supported-buildpacks). It's not hard to add more, [go add more](https://github.com/progrium/buildstep#adding-buildpacks)! Let's deploy 31 | the Heroku Node.js sample app. All you have to do is add a remote to name the app. It's created on-the-fly. 32 | 33 | $ cd node-js-sample 34 | $ git remote add progrium git@progriumapp.com:node-js-app 35 | $ git push progrium master 36 | Counting objects: 296, done. 37 | Delta compression using up to 4 threads. 38 | Compressing objects: 100% (254/254), done. 39 | Writing objects: 100% (296/296), 193.59 KiB, done. 40 | Total 296 (delta 25), reused 276 (delta 13) 41 | remote: -----> Building node-js-app ... 42 | remote: Node.js app detected 43 | remote: -----> Resolving engine versions 44 | 45 | ... blah blah blah ... 46 | 47 | remote: -----> Application deployed: 48 | remote: http://node-js-app.progriumapp.com 49 | 50 | You're done! 51 | 52 | ## Advanced installation (for development) 53 | 54 | The bootstrap script allows source URLs to be overridden to include customizations from your own 55 | repositories. The GITRECEIVE_URL and DOKKU_REPO environment variables 56 | may be set to override the defaults (see the bootstrap.sh script for how these apply). Example: 57 | 58 | $ wget j.mp/dokku-bootstrap 59 | $ chmod +x bootstrap.sh 60 | $ sudo DOKKU_REPO=https://github.com/yourusername/dokku.git ./bootstrap.sh 61 | 62 | ## Upgrading 63 | 64 | Dokku is in active development. You can update the deployment step and the build step separately. 65 | To update the deploy step (this is updated less frequently): 66 | 67 | $ cd ~/dokku 68 | $ git pull origin master 69 | $ sudo make install 70 | 71 | More frequently, the build step is updated. This is where the app "stack" lives and where buildpacks 72 | are supported. You can update this by running: 73 | 74 | $ cd ~/dokku/buildstep 75 | $ git pull origin master 76 | $ sudo make build 77 | 78 | Nothing needs to be restarted. Changes will take effect on the next push / deployment. 79 | 80 | ## Support 81 | 82 | You can use [Github Issues](https://github.com/progrium/dokku/issues), check [Troubleshooting](https://github.com/progrium/dokku/wiki/Troubleshooting) on the wiki, or join us on Freenode in #dokku 83 | 84 | ## Components 85 | 86 | * [Docker](https://github.com/dotcloud/docker) - Container runtime and manager 87 | * [Buildstep](https://github.com/progrium/buildstep) - Buildpack builder 88 | * [gitreceive](https://github.com/progrium/gitreceive) - Git push interface 89 | * [sshcommand](https://github.com/progrium/sshcommand) - Fixed commands over SSH 90 | 91 | ## Ideas for Improvements 92 | 93 | * Custom domain support for apps 94 | * HTTPS support on default domain 95 | * Support more buildpacks (see Buildstep) 96 | * Use dokku as the system user instead of git 97 | * Heroku-ish commands to be run via SSH (like [Dokuen](https://github.com/peterkeen/dokuen#available-app-sub-commands)) 98 | 99 | Looking to keep codebase as simple and hackable as possible, so try to keep your line count down. 100 | 101 | ## Things this project won't do 102 | 103 | * **Multi-host.** Not a huge leap, but this isn't the project for it. Maybe as Super Dokku. 104 | * **Multitenancy.** It's ready for it, but again, probably for Super Dokku. 105 | * **Client app.** Given the constraints, running commands remotely via SSH is fine. 106 | 107 | ## License 108 | 109 | MIT 110 | --------------------------------------------------------------------------------