diff --git a/.gitattributes b/.gitattributes
index c311834943b686b59167048f826c6acf34ab6a31..8d8020c68f303425d56928b4bb88836f630880d5 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,2 @@
-wynurz.sh eol=lf
-run.sh eol=lf
-*/build.sh eol=lf
+*.sh eol=lf
+make.py eol=lf
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..72cdf105feb688ccfad5a36221ecda5524cde4dc 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -0,0 +1,11 @@
+check_validity:
+    - stage: test
+    - script:
+      - python make.py newbox test
+      - cd test
+      - python ../make.py meta
+      - grep "1.0" metadata.json
+      - grep "example" metadata.json
+      - vagrant up
+      - vagrant destroy -f
+      - cd ..
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 0f0012a4003f5a64599f99d16a9cb1714ac36b42..0000000000000000000000000000000000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,37 +0,0 @@
-Chcesz jakąś typową VM-kę?
-
-Stwórz sobie jakąś gałąź o nazwie równej nazwie swojego boxa, zrób folder(y) o nazwie boxa,
-wrzuć tam `build.sh` (wywołwany jako root ) albo `build_as_vagrant.sh` (wywoływany jako
-uzytkownik _vagrant_), dorzuć _README.md_ którego trzecią linią będzie krótki opis,
-i się zrobi, wgra i będzie na [http://dev.dms-serwis.com.pl/vagrant/](http://dev.dms-serwis.com.pl/vagrant/)
-
-Np. maszyna **funky**
-**funky/build.sh**:
-```bash
-#!/usr/bin/env bash
-
-wynurz.sh java
-wynurz.sh cassandra
-wynurz.sh rabbitmq
-wynurz.sh zookeeper
-```
-
-**funky/README.md**:
-```markdown
-# funky
-
-java + cass + rmq + zk
-
-Maszyna z:
-* Cassandrą..
-```
-
-Sposób użycia będzie w README w katalogu po wbiciu `python make.py` w głównym katalogu.
-Zostanie doczepiony do twojego README. Ponowne wywołanie nie doczepią go ponownie.
-
-Generalnie buduje się tylko to co jest na dalej gałęzi. Po wywołaniu  `python make.py`
-wyślij to na repo i niech CI czyni magię. _.gitlab-ci.yml_ generowany jest przez 
-`python make.py`.
-
-**master** to taka czysta kartka - do robienia nowych branchĂłw tylko.
-Wpisz się w **mastera** 
diff --git a/README.md b/README.md
index 80629793d6ed94eb3ceca92a8cc3ea29466634c8..ed71a7181c91d1542c86fd5580f476dfc4e6720f 100644
--- a/README.md
+++ b/README.md
@@ -3,11 +3,83 @@
 Zbiór typowych boxów vagrantowych, co by kompilacje szybciej szły.
 Można dodawać własne!
 
-[Chcesz tworzyć własne typowe VMki?](/CONTRIBUTING.md)
-
 Zobacz dostępne [http://git.dms-serwis.com.pl/henrietta/vagrant-boxen/branches](branche)
 żeby widzieć jakie są vmki.
 
 Ew wbij na [http://dev.dms-serwis.com.pl/vagrant](http://dev.dms-serwis.com.pl/vagrant).
 
 W oparciu o *debian/contrib-jessie64*
+
+# Robienie własnych boxów
+Chcesz jakąś typową VM-kę?
+
+Stwórz sobie jakąś gałąź o nazwie równej nazwie swojego boxa. Możesz w `make.py` zmienić
+PREFIX, jeśli chcesz.
+
+Wywołaj:
+```bash
+python make.py newbox nazwa_boxa
+```
+Teraz baw się folderem o nazwie `nazwa_boxa`.
+
+Np. maszyna **funky**
+**funky/build.sh**:
+```bash
+#!/usr/bin/env bash
+
+wynurz.sh java
+wynurz.sh cassandra
+wynurz.sh rabbitmq
+wynurz.sh zookeeper
+```
+
+**funky/README.md**:
+```markdown
+# funky
+
+java + cass + rmq + zk
+
+Maszyna z:
+* Cassandrą..
+```
+Po ukończonej pracy odpal `python make.py`
+
+Sposób użycia będzie w README w katalogu po wbiciu `python make.py` w głównym katalogu.
+Zostanie doczepiony do twojego README. Ponowne wywołanie nie doczepią go ponownie.
+
+Generalnie buduje się tylko to co jest na dalej gałęzi. Po wywołaniu  `python make.py`
+wyślij to na repo i niech CI czyni magię. _.gitlab-ci.yml_ generowany jest przez 
+`python make.py`.
+
+Zawsze dostępna jest podczas buildu komenda `wynurz`. Wymaga ona roota, ale weźmie sobie sama za 
+pomocą _sudo_ jeśli go nie dasz. **NIE UŻYWAJ** _/vagrant/wynurz.sh_.
+
+Po pomyślnej kompilacji i deployu (dzieje się automatycznie) plik box można zassać z
+[http://dev.dms-serwis.com.pl/vagrant/](http://dev.dms-serwis.com.pl/vagrant/), albo
+po prostu wpisać wygenerowany przez make.py 
+
+**master** to taka czysta kartka - do robienia nowych branchĂłw tylko.
+Wpisz się w **mastera** 
+
+## wynurz
+
+Przyjmuje jeden argument. Dostępne to:
+* **java** - pobiera i instaluje Oracle Java 8 JRE
+* **node4** - pobiera i instaluje NodeJS 4.x
+* **node5** - pobiera i instaluje NodeJS 5.x
+* **jdk** - pobiera i instaluje Oracle Java JDK 8 w folderze uĹźytkownika _vagrant_.
+  * Nie ustawia zmiennych środowiskowych ŻADNYCH!
+  * Dostępna tylko dla użytkownika _vagrant_
+* **cassandra** - pobiera i instaluje Apache Cassandra 3.0.9
+  * Następnie po 30 sekundach w tle zatrzymuje ją
+  * Usługa będzie wstawać przy starcie VM-ki
+* **zookeeper** - pobiera i instaluje Apache ZooKeeper
+  * Następnie po 20 sekundach w tle zatrzymuje ją
+  * Usługa będzie wstawać przy starcie VM-ki
+* **rabbitmq** - pobiera i instaluje RabbitMQ 3.3.5
+  * Usługa będzie wstawać przy starcie VM-ki
+* **postgresql** - pobiera i instaluje PostgreSQL 9.4 
+  * User: postgres
+  * Hasło: postgres
+  * Połączenia: TCP z dowolnego adresu
+  
\ No newline at end of file
diff --git a/SkeletonVagrantfile b/SkeletonVagrantfile
index 1f5a67ec440f2552bc77d278cecd880280248928..504c163a364e14aa1b4c8a75497d64b86892877f 100644
--- a/SkeletonVagrantfile
+++ b/SkeletonVagrantfile
@@ -10,11 +10,14 @@ Vagrant.configure("2") do |config|
   config.vm.provision "shell", inline: <<-SHELL
     apt-get update
     apt-get install curl
+    cp /vagrant/wynurz.sh /usr/bin/wynurz
+    chmod ugo+rx /usr/bin/wynurz
 
     bash /vagrant/run.sh
 
     # Minify
     apt-get clean
+    rm -f /usr/bin/wynurz
     dd if=/dev/zero of=/EMPTY bs=1M
     rm -f /EMPTY
     rm -rf /tmp/*
diff --git a/make.py b/make.py
index d3c65b2072d05a015cb27f80482b1e30549b7989..6cc6bb845281c41372695ed55de7be5d45744766 100644
--- a/make.py
+++ b/make.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # coding=UTF-8
 """
 Run when
@@ -11,6 +12,31 @@ import sys
 
 PREFIX = 'henrietta/'
 
+def readfile(path, prefix=None, lines=False, strip=True):
+    if prefix is not None:
+        path = os.path.join(prefix, path)
+
+    with open(path, 'rb') as f:
+        if lines:
+            d = f.readlines()
+            if strip:
+                d = [q.strip() for q in d]
+        else:
+            d = f.read()
+            if strip:
+                d = d.strip()
+        return d
+
+def writefile(content, path, prefix=None):
+    if prefix is not None:
+        path = os.path.join(prefix, path)
+
+    with open(path, 'wb') as f:
+        if not isinstance(content, list):
+            content = [content]
+        for piece in content:
+            f.write(piece)
+
 if __name__ == '__main__':
     dirs = [dir for dir in os.listdir('.') if os.path.isdir(dir) or (dir != '.git')]
     exi = lambda box, sup: os.path.exists(os.path.join(box, 'build%s.sh' % (sup, )))
@@ -18,12 +44,12 @@ if __name__ == '__main__':
 
     if len(sys.argv) == 1:
         # Generate Gitlab CI file
-        with open('.gitlab-ci.yml', 'wb') as ci:
-            for box in boxes:
+        gitlabci = []
+
+        for box in boxes:
 
-                with open(os.path.join(box, 'README.md'), 'rb') as rin:
-                    readme = '\n---\n'.join(rin.read().split('\n---\n'))[:-1]
-                readme = readme + '''
+            readme = '\n---\n'.join(readfile('README.md', box).split('\n---\n'))[:-1]
+            readme = readme + '''
 ---
 
 Usage in Vagrantfile:
@@ -33,15 +59,14 @@ config.vm.box_url = "http://dev.dms-serwis.com.pl/vagrant/$BOX.box"
 ```
 '''.replace('$BOX', box).replace('$PREFIX', PREFIX)
 
-                with open(os.path.join(box, 'README.md'), 'wb') as fo:
-                    fo.write(readme)
+            writefile(readme, 'README.md', box)
 
-                try:
-                    os.unlink(os.path.join(box, 'metadata.json'))
-                except OSError:
-                    pass
+            try:
+                os.unlink(os.path.join(box, 'metadata.json'))
+            except OSError:
+                pass
 
-                ci.write('''
+            gitlabci.append('''
 deploy_$BOX:
   stage: deploy
   tags:
@@ -70,18 +95,43 @@ build_$BOX:
     - cd ..
 '''.replace('$BOX', box).replace('$PREFIX', PREFIX))
 
+        if len(gitlabci) == 0:
+            gitlabci = ['''check_validity:
+    - stage: test
+    - script:
+      - python make.py newbox test
+      - cd test
+      - python ../make.py meta
+      - grep "1.0" metadata.json
+      - grep "example" metadata.json
+      - vagrant up
+      - vagrant destroy -f
+      - cd ..
+''']
+
+        writefile(gitlabci, '.gitlab-ci.yml')
+
     if ' '.join(sys.argv).endswith('meta'):
         box = os.path.split(os.getcwd())[-1]
-        with open('README.md', 'rb') as mdin, open('metadata.json', 'wb') as mdout:
-            description = mdin.readlines()[2].strip()
 
+        readme = readfile('README.md', lines=True)
+        description = readme[2]
+
+        # Try get version
+        try:
+            version = readme[3]
+            if not version.startswith('Version:'):
+                raise IndexError()
+            ver = version.split(':')[1].strip()
+        except IndexError:
+            version = '1.0'
 
-            mdout.write('''{
+        writefile('''{
     "description": "$DESCRIPTION",
     "short_description": "$DESCRIPTION",
     "name": "$PREFIX$BOX",
     "versions": [{
-        "version": "1",
+        "version": "$VERSION",
         "status": "active",
         "description_html": "<p>$DESCRIPTION</p>",
         "description_markdown": "$DESCRIPTION",
@@ -91,4 +141,38 @@ build_$BOX:
         }]
     }]
 }
-'''.replace('$DESCRIPTION', description).replace('$BOX', box).replace('$PREFIX', PREFIX))
+'''.replace('$DESCRIPTION', description).replace('$BOX', box).replace('$PREFIX', PREFIX).replace('$VERSION', VERSION),
+    'metadata.json')
+
+    if len(sys.argv) == 3:
+        if sys.argv[-2] == 'newbox':
+            box = sys.argv[-1]
+            os.mkdir(box)
+            writefile('''# $BOX
+
+This is description of the box. It will be copied. Keep it short and single-line. Don't remove the line break before.
+Version: 1.0
+
+Write what this box consists of and how it behaves.
+First four lines have a special meaning - dont move them around. Change only version number, not the word.
+
+---
+
+This section will be automatically replaced by `python make.py` with auto-generated
+content of Vagrantfile that will refer to this box.
+'''.replace('$BOX', box).replace('$PREFIX', PREFIX), 'README.md', box)
+
+            writefile('''#!/bin/bash
+
+# This will be executed during build process as root
+# You can delete it if you want to.
+# cd into a directory if you depend on a particular working directory.
+''', 'build.sh', box)
+
+            writefile('''#!/bin/bash
+
+# This will be executed during build process as user Vagrant
+# You can delete it if you want to.
+# cd into a directory if you depend on a particular working directory.
+''', 'build_as_vagrant.sh', box)
+
diff --git a/run.sh b/run.sh
index fee128569ff8b425851c4f9a068e70a90f5fb2b7..f6568e248f8d36676f5700f561e111cf1f8aa20a 100644
--- a/run.sh
+++ b/run.sh
@@ -5,8 +5,10 @@ shutdown -h +30 "Timeout on VM creation"
 export PATH=$PATH:/vagrant
 chmod ugo+x /vagrant/*.sh
 
-if [ ! -e "/vagrant/build.sh" ]; then
-    sudo -H -u vagrant bash /vagrant/build_as_vagrant.sh
-else
+if [ -e "/vagrant/build.sh" ]; then
     bash /vagrant/build.sh
-fi
\ No newline at end of file
+fi
+
+if [ -e "/vagrant/build.sh" ]; then
+    sudo -H -u vagrant bash /vagrant/build_as_vagrant.sh
+fi
diff --git a/wynurz.sh b/wynurz.sh
index 6a255be221e137b993f74fc78800b74185127230..58807e0e95c6e1ab2b2795a9e2705cfed9bba56a 100644
--- a/wynurz.sh
+++ b/wynurz.sh
@@ -1,8 +1,10 @@
 #!/usr/bin/env bash
 
-# Typowe polecenia do instalowania typowych rzeczy
-#
-#
+if [ "$EUID" -ne 0 ]; then
+  echo "Invoked as non-root, sudoing..."
+  sudo -- wynurz "$@"
+  exit $?
+fi
 
 if [ $1 == "java" ]; then
     # Oracle Java JRE
@@ -29,16 +31,16 @@ if [ $1 == "node5" ]; then
 fi
 
 if [ $1 == "jdk" ]; then
-    sudo wget -nv http://dev.dms-serwis.com.pl/misc/jdk-8u121-linux-x64.tar.gz
-    sudo tar xzf jdk-8u121-linux-x64.tar.gz
-    sudo rm -f jdk-8u121-linux-x64.tar.gz
-    sudo update-alternatives --install /usr/bin/java java /home/vagrant/jdk1.8.0_121/bin/java 100
-    sudo update-alternatives --install /usr/bin/javac javac /home/vagrant/jdk1.8.0_121/bin/javac 100
-    sudo update-alternatives --install /usr/bin/jar jar /home/vagrant/jdk1.8.0_121/bin/jar 100
-    sudo update-alternatives --install /usr/bin/jarsigner jarsigner /home/vagrant/jdk1.8.0_121/bin/jarsigner 100
+    cd /home/vagrant
+    wget -nv http://dev.dms-serwis.com.pl/misc/jdk-8u121-linux-x64.tar.gz
+    tar xzf jdk-8u121-linux-x64.tar.gz
+    rm -f jdk-8u121-linux-x64.tar.gz
+    update-alternatives --install /usr/bin/java java /home/vagrant/jdk1.8.0_121/bin/java 100
+    update-alternatives --install /usr/bin/javac javac /home/vagrant/jdk1.8.0_121/bin/javac 100
+    update-alternatives --install /usr/bin/jar jar /home/vagrant/jdk1.8.0_121/bin/jar 100
+    update-alternatives --install /usr/bin/jarsigner jarsigner /home/vagrant/jdk1.8.0_121/bin/jarsigner 100
 fi
 
-
 if [ $1 == "cassandra" ]; then
     # Install Apache Cassandra
     echo "deb http://debian.datastax.com/community stable main" > /etc/apt/sources.list.d/cassandra.sources.list