diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000000000000000000000000000000000000..fa7e9994b818d03e0accdfd7fc61d2c569f94ad2
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,217 @@
+#!/usr/bin/env groovy
+
+/*
+With the provided script, the firmware can be build with jenkins. Setup
+a Pipeline job and configure the pipeline definition to "Pipeline script
+from SCM". Supply as SCM git and as repository
+https://github.com/freifunk-stuttgart/site-ffs.git. All other options
+can be left at their default. If neccessary configure the branch
+specifier. The job parameters will be filled when the job is started the
+first time. If you do not want to build all architectures, cancel the
+buold and trigger a parameterized build where you can now choose the
+architectures to be build.
+
+The init and manifest stage will be executed on the master, all other
+stages are executed on any node. This job can use eight build slaves to
+build the firmware. 
+
+On each slave, nproc is used to run make with all available cpu cores. 
+
+Per default, all broken targets will be build also. You can choose to
+run make clean before building each architecture. You can check
+clean_workspace to build entirely from scratch. 
+
+Note that bcrm2708_2710 is not supported with v2017.1.7, but on gluon
+master branch. It will be supported in a later release. 
+
+If you want to use a different gluon version, you can modify the gluon
+parameter, if you want to use a custom site-ffs version, you can modify
+the site parameter
+*/
+
+def fetchSources() {
+    checkout changelog: false, poll: false, scm: [$class: 'GitSCM', branches: [[name: "${params.gluon}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[url: 'https://github.com/freifunk-gluon/gluon.git']]]
+    dir('site') {
+        checkout changelog: false, poll: false, scm: [$class: 'GitSCM', branches: [[name: "${params.site}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[url: 'https://github.com/freifunk-stuttgart/site-ffs.git']]]
+    }
+}
+
+def buildArch(archs) {
+    echo "step ${STAGE_NAME}"
+    if (params.clean_workspace) {
+        sh 'rm -Rf *'
+    }
+    fetchSources()
+    dir('output') { deleteDir() }
+
+    if (params.make_clean) {
+        for (arch in archs) {
+            sh "nice make GLUON_TARGET=${arch} clean"
+        }
+    }
+    sh "nice make update"
+    for (arch in archs) {
+        if (params.verbose) {
+            sh "nice make -j1 V=s BROKEN=${params.broken} GLUON_BRANCH=stable GLUON_TARGET=${arch} BUILD_DATE=${BUILD_DATE}"
+        } else {
+            sh "nice make -j`nproc` BROKEN=${params.broken} GLUON_BRANCH=stable GLUON_TARGET=${arch} BUILD_DATE=${BUILD_DATE}"
+        }
+    }
+    allArchs << "${STAGE_NAME}"
+    sh "find output/images"
+    sh "find output/packages"
+    stash name: "${STAGE_NAME}", includes: "output/images/*/*, output/packages/*/*/*/*"
+}
+
+pipeline {
+    agent none
+    parameters {
+        booleanParam(name: 'ar71xx_generic', defaultValue: true, description: '')
+        booleanParam(name: 'ar71xx_mikrotik', defaultValue: true, description: '')
+        booleanParam(name: 'ar71xx_nand', defaultValue: true, description: '')
+        booleanParam(name: 'ar71xx_tiny', defaultValue: true, description: '')
+        booleanParam(name: 'brcm2708_bcm2708', defaultValue: true, description: '')
+        booleanParam(name: 'brcm2708_bcm2709', defaultValue: true, description: '')
+        booleanParam(name: 'brcm2708_bcm2710', defaultValue: false, description: '')
+        booleanParam(name: 'ipq806x', defaultValue: true, description: '')
+        booleanParam(name: 'mpc85xx_generic', defaultValue: true, description: '')
+        booleanParam(name: 'mvebu', defaultValue: true, description: '')
+        booleanParam(name: 'ramips_mt7621', defaultValue: true, description: '')
+        booleanParam(name: 'ramips_mt7628', defaultValue: true, description: '')
+        booleanParam(name: 'ramips_rt305x', defaultValue: true, description: '')
+        booleanParam(name: 'sunxi', defaultValue: false, description: '')
+        booleanParam(name: 'x86_generic', defaultValue: true, description: '')
+        booleanParam(name: 'x86_geode', defaultValue: true, description: '')
+        booleanParam(name: 'x86_64', defaultValue: true, description: '')
+        booleanParam(name: 'verbose', defaultValue: false, description: 'build with -j1 and V=s for debugging build errors')
+        booleanParam(name: 'make_clean', defaultValue: false, description: 'execute make clean before building each architecture' )
+        booleanParam(name: 'clean_workspace', defaultValue: false, description: 'delete all files in workspace before building' )
+        choice(name: 'broken', choices: '1\n0', description: 'wether to build broken targets or not')
+        string(defaultValue: "refs/tags/v2017.1.7", name: 'gluon', description: 'gluon release tag')
+        string(defaultValue: "*/master", name: 'site', description: 'site release tag, branch or commit')
+        string(defaultValue: "", name: 'deploy_to', description: 'target for rsync\nExample: www@netinfo:/home/www/html/firmware/gluon/archive/@leonard')
+    }
+
+    options {
+        timestamps()
+    }
+
+    stages {
+        stage('init') {
+            agent { label 'master'}
+            steps { script {
+                allArchs = []
+                fetchSources()
+                BUILD_DATE = sh(returnStdout: true, script: 'date +%Y-%m-%d').trim()
+                echo "${BUILD_DATE} in setup"
+            } }
+        }
+        stage('compile') {
+            parallel {
+                stage('ar71xx') {
+                    agent any
+                    when { expression {return params.ar71xx_generic || params.ar71xx_mikrotik || params.ar71xx_nand || params.ar71xx_tiny } }
+                    steps { script { 
+                        def archs = []
+                        if (params.ar71xx_generic) { archs << 'ar71xx-generic'}
+                        if (params.ar71xx_mikrotik) { archs << 'ar71xx-mikrotik'}
+                        if (params.ar71xx_nand) { archs << 'ar71xx-nand'}
+                        if (params.ar71xx_tiny) { archs << 'ar71xx-tiny'}
+                        buildArch(archs)
+                    } }
+                }
+                stage('brcm2708') {
+                    agent any
+                    when { expression {return params.brcm2708_bcm2708 || params.brcm2708_bcm2709 || params.brcm2708_bcm2710 } }
+                    steps { script { 
+                        def archs = []
+                        if (params.brcm2708_bcm2708) { archs << 'brcm2708-bcm2708'}
+                        if (params.brcm2708_bcm2709) { archs << 'brcm2708-bcm2709'}
+                        if (params.brcm2708_bcm2710) { archs << 'brcm2708-bcm2710'}
+                        echo "Archs for ${STAGE_NAME}: ${archs}"
+                        buildArch(archs)
+                    } }
+                }
+                stage('ipq806x') {
+                    agent any
+                    when { expression {return params.ipq806x } }
+                    steps { script { 
+                        def archs = []
+                        buildArch(["ipq806x"])
+                    } }
+                }
+                stage('mpc85xx-generic') {
+                    agent any
+                    when { expression {return params.mpc85xx_generic } }
+                    steps { script { 
+                        buildArch(["mpc85xx-generic"])
+                    } }
+                }
+                stage('mvebu') {
+                    agent any
+                    when { expression {return params.mvebu } }
+                    steps { script { 
+                        buildArch(["${STAGE_NAME}"])
+                    } }
+                }
+                stage('ramips') {
+                    agent any
+                    when { expression {return params.ramips_mt7621 || params.ramips_mt7628 || params.ramips_rt305x } }
+                    steps { script { 
+                        def archs = []
+                        if (params.ramips_mt7621) { archs << 'ramips-mt7621' }
+                        if (params.ramips_mt7628) { archs << 'ramips-mt7628' }
+                        if (params.ramips_rt305x) { archs << 'ramips-rt305x' }
+                        buildArch(archs)
+                    } }
+                }
+                stage('sunxi') {
+                    agent any
+                    when { expression {return params.sunxi } }
+                    steps { script { 
+                        buildArch(["${STAGE_NAME}"])
+                    } }
+                }
+                stage('x86') {
+                    agent any
+                    when { expression {return params.x86_generic || params.x86_genode || params.x86_64 } }
+                    steps { script { 
+                        def archs = []
+                        if (params.x86_generic) { archs << 'x86-generic' }
+                        if (params.x86_genode) { archs << 'x86-genode' }
+                        if (params.x86_64) { archs << 'x86-64' }
+                        echo "Archs for ${STAGE_NAME}: ${archs}"
+                        buildArch(archs)
+                    } }
+                }
+            }
+        }
+        
+        stage('manifest and deploy') {
+            agent { label 'master'}
+            steps { script {
+                    fetchSources()
+                    echo "step ${STAGE_NAME}"
+                    echo "Archs: ${allArchs}"
+                    dir('output') { deleteDir() }
+                    
+                    for (arch in allArchs) {
+                        unstash "${arch}"
+                    }
+                    
+                    sh """
+                        make manifest GLUON_BRANCH=stable
+                        make manifest GLUON_BRANCH=beta
+                        make manifest GLUON_BRANCH=nightly
+                    """
+                    archiveArtifacts artifacts: 'output/images/*/*, output/packages/*/*/*/*', fingerprint: true
+                    if (deploy_to != "") {
+                        sh "rsync -avx output/images/factory ${params.deploy_to}/${BUILD_DATE}_${BUILD_TAG}/"
+                        sh "rsync -avx output/images/sysupgrade ${params.deploy_to}/${BUILD_DATE}_${BUILD_TAG}/"
+                        sh "rsync -avx output/packages ${params.deploy_to}/${BUILD_DATE}_${BUILD_TAG}/"
+                    }
+            } }
+        }
+    }
+}
+