Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/Xyic0re/mkdocs
Browse files Browse the repository at this point in the history
  • Loading branch information
popbangshwang committed Mar 9, 2024
2 parents 5a43031 + 45105e6 commit e6fa4a2
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 56 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
stopit.sh
nginx.key
nginx-certificate.crt
.env
21 changes: 10 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
FROM nginx:alpine

# install python and pip3 needed for installation of mkdocs
# Install base system
RUN apk add --no-cache \
python3 \
py3-pip \
nodejs \
openssl \
git \
# Install Build dependencies (for some mkdocs requirements)
# Install build dependencies
&& apk add --no-cache --virtual .build-deps \
# build-base \
# curl \
# wget \
# make \
# python3-dev \
# && pip3 install \
# wheel \
&& pip3 install \
flask \
&& pip3 install \
fastapi \
&& pip3 install \
waitress \
&& pip3 install \
mkdocs-material \
&& rm -rf "$HOME/.cache" \
Expand All @@ -27,6 +26,6 @@ COPY nginx.key /etc/nginx/certificate/nginx.key
COPY .htpasswd /etc/nginx/.htpasswd

# Copy in webhook and startup script
COPY webhook.js /opt/webhook/webhook.js
COPY webhook.py /opt/webhook/webhook.py
COPY mkdocs.sh /docker-entrypoint.d/40-mkdocs.sh
RUN chmod +x /docker-entrypoint.d/40-mkdocs.sh
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Mkdocs-material docker container with nginx/basic auth/ssl - self signed/webhook for pushes and auto mkdocs rebuild
# Lightweight +-200MB Mkdocs-material docker container with nginx/basic auth/ssl - self signed/webhook for pushes and auto mkdocs rebuild

### https://squidfunk.github.io/mkdocs-material/

Expand All @@ -11,7 +11,7 @@
| └── <additional docs go here>
├── mkdocs.yml
├── mkdocs.sh
├── webhook.js
├── webhook.py
├── Dockerfile
├── nginx.conf
├── run.sh
Expand All @@ -38,13 +38,14 @@ git clone https://github.com/<username>/<repo>.git && cd mkdocs

## Setup and Run

Create a Github webhook - if you're using ngrok replace 'Payload URL' with ngrok address eg: https://91f1-226-13-123-216.ngrok-free.app (without the 8080 since this is done in you ngrok setup)
Create a Github webhook - if you're using ngrok replace 'Payload URL' with ngrok address eg: https://91f1-226-13-123-216.ngrok-free.app/hooked (without the 8080 since this is done in you ngrok setup)
- webhook Payload URL - https//FQDN/hooked - **/hooked is important**
- make sure you have 8080 opened on you firewall
- Content type: application/json
- Secret: enter a secret for this webhook
- Which events: just the push event
- Active: tick
![alt text](image.png)
![alt text](image-1.png)

```bash
chmod +x run.sh && ./run.sh
Expand All @@ -53,4 +54,9 @@ chmod +x run.sh && ./run.sh
**Run**
```bash
./run.sh
```
```

## Extras

- replace nginx-certificate.crt with your own crt if you have it
- mkdocs plugins can be installed - modify mkdocs.yml and Dockerfile for pip install <plugin>
Binary file added image-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 3 additions & 4 deletions mkdocs.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/bin/sh
# vim:sw=4:ts=4:et

set -e

Expand All @@ -10,11 +9,11 @@ entrypoint_log() {
}

# perform the initial clone and build for mkdocs
cd /opt/mkdocs
mkdocs build
GIT_REPO=$(echo $CRYPT_GIT_REPO | openssl enc -aes-256-ctr -pbkdf2 -a -k $RAND_VAR -d)
git clone $GIT_REPO /opt/mkdocs && cd /opt/mkdocs && mkdocs build

# run the weblistner on port 8080 for github pushes
node /opt/webhook/webhook.js &
cd /opt/webhook && python webhook.py &

ME=$(basename "$0")

Expand Down
62 changes: 43 additions & 19 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,43 @@
# set first_run=0 to run setup
first_run=0


if ! [ -e ./.env ] ; then
touch ./.env
fi
if ! [ -w ./.env ] ; then
printf 'cannot write to %s\n' ./.env
exit 1
fi

if [ $first_run -eq 0 ]; then
if [ $(grep -c 'git clone' ./mkdocs.sh) -eq 1 ]; then
printf '(skipped) - mkdocs.sh already contains repo information - edit manually and remove line 13\n'

if [ $(grep -c 'RAND_VAR=' ./.env) -eq 1 ]; then
printf '(skipped) - .env already contains "RAND_VAR" - edit manually\n'
else
printf 'Injecting RAND_VAR into .env\n'
rand_var=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 42; echo)
echo "RAND_VAR=$rand_var" >> ./.env
printf 'done\n'
fi

if [ $(grep -c 'CRYPT_GIT_REPO=' ./.env) -eq 1 ]; then
printf '(skipped) - .env already contains "CRYPT_GIT_REPO" - edit manually\n'
else
printf 'Injecting repository info into ./mkdocs.sh\n'
printf 'Injecting CRYPT_GIT_REPO into ./env\n'
read -rp 'Enter your repository clone address - eg: https://<PAT>@github.com/username/repo.git : ' git_address
sed -i "13 s#^#git clone \""$git_address"\" /opt/mkdocs\n#" ./mkdocs.sh
crypt_git_address=$(echo $git_address | openssl enc -aes-256-ctr -A -pbkdf2 -a -k $rand_var)
echo "CRYPT_GIT_REPO=$crypt_git_address" >> ./.env
printf 'done\n'
fi

if [ $(grep -c 'const webhook_secret' ./webhook.js) -eq 1 ]; then
printf '(skipped) - webhook.js already contains secret - edit manually and remove line 2\n'
if [ $(grep -c 'CRYPT_SECRET=' ./.env) -eq 1 ]; then
printf '(skipped) - .env already contains "CRYPT_SECRET" - edit manually\n'
else
printf 'Injecting secret into ./webhook.js\n'
printf 'Injecting CRYPT_SECRET into .env\n'
read -rp 'Enter your webhook secret ' secret
sed -i "2 s#^#const webhook_secret = \""$secret"\";\n#" ./webhook.js
crypt_secret=$(echo $secret | openssl enc -aes-256-ctr -A -pbkdf2 -a -k $rand_var)
echo "CRYPT_SECRET=$crypt_secret" >> ./.env
printf 'done\n'
fi

Expand All @@ -32,20 +53,22 @@ if [ $first_run -eq 0 ]; then
if [[ -f ./nginx-certificate.crt ]]; then
read -rp 'nginx-certificate.crt already exists - do you wish to regenerate it? (y/N):' regenerate_cert
if [[ "$regenerate_cert" =~ ^([yY][eE][sS]|[yY])$ ]]; then
printf '\n'
printf 'Generating self signed ssl certificate\n'
read -rp "Populating 'CN' field - enter your FQDN or host's IP: " CN_field
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out nginx-certificate.crt -keyout nginx.key -subj "/C=AU/ST=QLD/L=Brisbane/O=Global Security/OU=IT Department/CN=$CN_field"
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out nginx-certificate.crt -keyout nginx.key -subj "/C=AU/ST=QLD/L=Brisbane/O=Global Security/OU=IT Department/CN=$CN_field"
fi
else
printf '\n'
printf 'Generating self signed ssl certificate\n'
read -rp "Populating 'CN' field - enter your FQDN or host's IP: " CN_field
read -rp "Populating 'CN' field - enter your FQDN or host's IP (local IP if using ngrok): " CN_field
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out nginx-certificate.crt -keyout nginx.key -subj "/C=AU/ST=QLD/L=Brisbane/O=Global Security/OU=IT Department/CN=$CN_field"
fi

if [[ -f ./.htpasswd ]]; then
read -rp '.htpasswd already exists - do you wish to regenerate it? (y/N):' regenerate_htpasswd
if [[ "$regenerate_htpasswd" =~ ^([yY][eE][sS]|[yY])$ ]]; then
printf 'Configuring basic auth for nginx - generating .htpasswd\n'
printf 'Configuring basic auth for nginx - generating .htpasswd\n'
read -rp 'Enter your user: ' username
htpasswd -c ./.htpasswd $username
printf "Added user $username to .htpasswd\n To add additional user(s) run 'htpasswd ./.htpasswd <user> or edit the file directly\n"
Expand All @@ -57,12 +80,12 @@ if [ $first_run -eq 0 ]; then
printf "Added user $username to .htpasswd\n To add additional user(s) run 'htpasswd ./.htpasswd <user> or edit the file directly\n"
fi

read -rp 'add an additional user(s)? (y/N): ' more_users
read -rp 'add additional user(s)? (y/N): ' more_users
while [[ "$more_users" =~ ^([yY][eE][sS]|[yY])$ ]]; do
read -rp 'Enter your user: ' add_user
htpasswd ./.htpasswd $add_user
printf "Added user $add_user to .htpasswd\n"
read -rp 'add an additional user(s)? (y/N): ' more_users
read -rp 'add additional user(s)? (y/N): ' more_users
done

printf 'Config done... building image\n'
Expand All @@ -73,14 +96,15 @@ if [ $first_run -eq 0 ]; then
printf 'Image built - mkdocs\n'
fi

read -rp "Do you want to run the container now? (y/N): " runit
read -rp "Run the container now? (y/N): " runit
if [[ "$runit" =~ ^([yY][eE][sS]|[yY])$ ]]; then
docker run -d --name mkdocs --mount type=volume,target=/opt/mkdocs --publish 443:443/tcp --publish 80:80/tcp --publish 8080:8080/tcp mkdocs
docker run -d --env-file=./.env --name mkdocs --mount type=volume,target=/opt/mkdocs --publish 443:443/tcp --publish 80:80/tcp --publish 8080:8080/tcp mkdocs
else
printf 'You can run the container with this script or using docker run with: \n docker run -d --name mkdocs --mount type=volume,target=/opt/mkdocs --publish 443:443/tcp --publish 80:80/tcp --publish 8080:8080/tcp mkdocs\n'
printf '\n'
printf 'Run the container with this script or using docker run with: \n docker run -d --env-file=./.env --name mkdocs --mount type=volume,target=/opt/mkdocs --publish 443:443/tcp --publish 80:80/tcp --publish 8080:8080/tcp mkdocs\n'
fi
# Set first_run to 1 - subsequent runs will not perform setup tasks
printf '-------------------------------------------------------------------'
printf "Setup complete - setting 'first_run=1' reset this to zero to rerun setup\n"
printf 'You can run the container with this script or using docker run with: \n docker run -d --name mkdocs --mount type=volume,target=/opt/mkdocs --publish 443:443/tcp --publish 80:80/tcp --publish 8080:8080/tcp mkdocs\n'
printf '\n'
printf "Setup complete - setting 'first_run=1' manually reset this to zero to rerun setup\n"
printf 'Run the container with this script or using docker run with: \n docker run -d --env-file=./.env --name mkdocs --mount type=volume,target=/opt/mkdocs --publish 443:443/tcp --publish 80:80/tcp --publish 8080:8080/tcp mkdocs\n'
sed -i "3 s#first_run=0#first_run=1#" ./run.sh
17 changes: 0 additions & 17 deletions webhook.js

This file was deleted.

74 changes: 74 additions & 0 deletions webhook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from flask import Flask, request, abort
from fastapi import HTTPException, WebSocketException
import hmac
import hashlib
import base64
import subprocess


webhook = Flask(__name__)

# Get rand_var from environment variable
rand_cmd = subprocess.check_output(["echo $RAND_VAR"], shell=True, encoding="utf-8")
rand_var=str(rand_cmd).strip()
#print("rand_var")
#print(rand_var)

# Run 'echo' and pipe the output to 'openssl'
secret_cmd = subprocess.Popen(["echo $CRYPT_SECRET"], shell=True, stdout=subprocess.PIPE)
#print(secret_cmd.stdout)
# Run 'openssl' and pipe the output of 'echo' to it
openssl_cmd = subprocess.check_output(["openssl", "enc", "-aes-256-ctr", "-pbkdf2", "-d", "-a", "-k", rand_var], stdin=secret_cmd.stdout, encoding="utf-8")
secret_token=str(openssl_cmd).strip()
#print("..")
#print(secret_token)
#print("...")

def verify_signature(payload_body, secret_token, signature_header):

"""Verify that the payload was sent from GitHub by validating SHA256.
Raise and return 403 if not authorized.
Args:
payload_body: original request body to verify (request.body())
secret_token: GitHub app webhook token (WEBHOOK_SECRET)
signature_header: header received from GitHub (x-hub-signature-256)
https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries
"""
if not signature_header:
raise HTTPException(status_code=403, detail="x-hub-signature-256 header is missing!")
hash_object = hmac.new(secret_token.encode('utf-8'), msg=payload_body, digestmod=hashlib.sha256)
expected_signature = "sha256=" + hash_object.hexdigest()
return hmac.compare_digest(expected_signature, signature_header)

@webhook.route('/hooked', methods=['POST'])
def handle_webhook():
# Get raw body
payload_body = request.get_data()
#print("body")
#print(payload_body)
# Get signature header
signature_header = request.headers.get('X-Hub-Signature-256')
#print("signature_header")
#print(signature_header)
verified = verify_signature(payload_body, secret_token, signature_header)

if not verified:
print("not verified")
abort(401)

# git pull
git_pull_output = subprocess.check_output(['git', 'pull'], cwd="/opt/mkdocs")
print("git pull output")
print(git_pull_output)
# mkdocs build
mkdocs_build_output = subprocess.check_output(['mkdocs', 'build'], cwd="/opt/mkdocs")
print("mkdocs build output")
print(mkdocs_build_output)

print("verified")
return ('', 200)

# use waitress to serve the webhook on all interfaces port 8080
if __name__ == "__main__":
from waitress import serve
serve(webhook, host="0.0.0.0", port=8080)

0 comments on commit e6fa4a2

Please sign in to comment.