diff --git a/.gitignore b/.gitignore
index a7f40ab09a5c364227b04c5438732797cb400aa1..08ff0931c399e8017306350235e6cf9cf0e0cbc2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,5 @@ tags
 conanbuildinfo.cmake
 conaninfo.txt
 CMakeLists.txt.user*
+
+*.pyc
diff --git a/Jenkinsfile b/Jenkinsfile
index ed8f80d8e04117b23ca45be714a6adb5ffc0c695..2c2cf922a3f1b135f24f5bad8ccc6440e5b77ccb 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -22,6 +22,9 @@ node('master') {
     if (helper.isRelease()) {
         builders['msvc32'] = { load 'scripts/jenkins/msvc32.groovy' }
     }
+    if (helper.isOriginMaster()) {
+        builders['docs'] = { load 'scripts/jenkins/docs.groovy' }
+    }
 
     parallel builders
 
diff --git a/scripts/jenkins/clang.groovy b/scripts/jenkins/clang.groovy
index edb7b7fb0c6fa8ccb7980598464a088ea98c72c1..e66b70cbdbfdb04d90f6f8983f2dc22e7f42c6b5 100644
--- a/scripts/jenkins/clang.groovy
+++ b/scripts/jenkins/clang.groovy
@@ -1,7 +1,12 @@
 node('docker') {
-    def configure = load 'scripts/jenkins/lib/configure.groovy'
-    def build     = load 'scripts/jenkins/lib/build.groovy'
-    def post      = load 'scripts/jenkins/lib/post.groovy'
+    stage 'Checkout (Clang)'
+    dir('ogs') {
+        checkout scm
+
+        configure = load 'scripts/jenkins/lib/configure.groovy'
+        build     = load 'scripts/jenkins/lib/build.groovy'
+        post      = load 'scripts/jenkins/lib/post.groovy'
+    }
 
     def defaultDockerArgs = '-v /home/jenkins/.ccache:/usr/src/.ccache'
     def defaultCMakeOptions =
@@ -11,9 +16,6 @@ node('docker') {
         '-DOGS_UNDEFINED_BEHAVIOR_SANITIZER=ON ' +
         '-DOGS_BUILD_UTILS=ON'
 
-    stage 'Checkout (Clang)'
-    dir('ogs') { checkout scm }
-
     docker.image('ogs6/clang-base:latest').inside(defaultDockerArgs) {
         stage 'Configure (Clang)'
         configure.linux 'build', "${defaultCMakeOptions}"
diff --git a/scripts/jenkins/docs.groovy b/scripts/jenkins/docs.groovy
new file mode 100644
index 0000000000000000000000000000000000000000..453e0a3f3080897b0978de8e9cf1aa093d57d131
--- /dev/null
+++ b/scripts/jenkins/docs.groovy
@@ -0,0 +1,31 @@
+node('docker') {
+    def defaultCMakeOptions =
+        '-DOGS_LIB_BOOST=System ' +
+        '-DOGS_LIB_VTK=System'
+
+    stage 'Checkout (Docs)'
+    dir('ogs') { checkout scm }
+
+    docker.image('ogs6/gcc-gui:latest').inside() {
+        stage 'Configure (Docs)'
+        configure.linux 'build', "${defaultCMakeOptions}"
+
+        stage 'Generate (Docs)'
+        build.linux 'build', 'doc'
+    }
+
+    stage 'Reports (Docs)'
+    publishHTML(target: [allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false,
+        reportDir: 'build/docs', reportFiles: 'index.html', reportName: 'Doxygen'])
+    step([$class: 'WarningsPublisher', canResolveRelativePaths: false,
+        canRunOnFailed: true, consoleParsers: [[parserName: 'Doxygen']],
+        defaultEncoding: '', excludePattern: '', healthy: '',
+        includePattern: '', messagesPattern: '', unHealthy: '',
+        unstableNewAll: '0', useStableBuildAsReference: true])
+
+    if (helper.isOriginMaster()) {
+        stage 'Deploy (Docs)'
+        sh 'rsync -a --delete --stats build/docs/ ' +
+            'web@doxygen.opengeosys.org:/www/doxygenogs'
+    }
+}