commit d5cc887a593711a7ac3d0a623e965a6cb5c29f30 Author: basebuilder Date: Wed Mar 20 13:28:42 2024 +0100 init clone of @adz code from offline.place diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b25a745 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,50 @@ +FROM alpine:3.19.0 + +# Paths +ARG BIN_TARGET=/usr/local/bin + +# Versions +ARG WEBHOOKD_VERSION=1.17.3 +ARG HUGO_VERSION=0.122.0 + +# User +ARG USER=webhookd +ARG UID=1000 + +# Hugo configuration +ENV HUGO_GIT_URL= +ENV HUGO_WORKING_DIR=/home/$USER/website +ENV HUGO_PUBLIC_DIR=/home/$USER/public + +# Create non-root user +RUN adduser \ + --disabled-password \ + --gecos "" \ + --uid "$UID" \ + "$USER" + +# Install dependencies +RUN apk add --no-cache git bash curl libc6-compat go openssh-client + +# Install webhookd for scripts we can trigger via external HTTP requests +RUN curl -o webhookd.tgz --fail -L "https://github.com/ncarlier/webhookd/releases/download/v${WEBHOOKD_VERSION}/webhookd-linux-amd64.tgz" && \ + tar xvzf webhookd.tgz -C $BIN_TARGET + +# Install hugo, the static page generator +RUN curl -o hugo.tgz --fail -L "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz" && \ + tar xvzf hugo.tgz -C $BIN_TARGET + +# Clean up +RUN rm webhookd.tgz && \ + rm hugo.tgz && \ + rm $BIN_TARGET/README.md && \ + rm $BIN_TARGET/CHANGELOG.md && \ + rm $BIN_TARGET/LICENSE + +EXPOSE 8080 + +USER $USER + +RUN mkdir $HUGO_PUBLIC_DIR + +CMD [ "webhookd" ] diff --git a/README.md b/README.md new file mode 100644 index 0000000..d5f2c9d --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +Parasol Static Site +==================== + +The following starter is two container setup works well for two docker +containers for website building and webhook listener for changes. + +Perhaps it can be repurposed as a recipe?! + + + +### Deploy tools with Docker + +Docker setup to host a `hugo` static website with a `nginx` HTTP server. The website can be updated and built via an external HTTP request using `webhookd` which pulls the latest version from a .git repository. + +## Requirements + +* `docker` +* `docker-compose` + +## Deployment + +By default the hook server listens at port `8080` while the static website is hosted on port `9090`, the `HUGO_GIT_URL` variable is set to this very repository. + +It is recommended to use an reverse proxy to move both endpoints behind authentication, DNS, TLS etc. + +```bash +# Start nginx server and webhook / build server in background (-d) +docker-compose up -d + +# Rebuild docker files after something changed +docker-compose up --build -d +``` + +Do not forget to run the hook for the first time to trigger building the website. This does not happen automatically. + +## Usage + +```bash +# Trigger deploy hook via HTTP request +curl -v -XPOST http://localhost:8080/deploy +``` + +It is recommended to configure your webhook endpoint to be protected by HTTP Basic authentication. To call that hook generate the header like that: + +```bash +# Generate authentication token +echo -n user:password | base64 + +# Trigger deploy hook via authenticated HTTP request +curl -v XPOST -H "Authorization: Basic " https://hook.com/deploy +``` + +## Private repository + +In case you're pulling from a private repository, you need to point at the folder where the ssh keys live. For this, create an `.env` file or use the `-e` command line argument when launching docker: + +```bash +SSH_DIR_PATH=/home/myuser/.ssh +``` + +You might want to adjust your configs as docker will not have write access to adjust `known_hosts` etc: + +``` +Host codeberg.org + StrictHostKeyChecking no +``` + +## Development + +```bash +# Build docker image based on Dockerfile +sudo docker build . -t offline + +# Run container from this image +sudo docker run \ + -p 8080:8080 \ + -v ./scripts:/scripts \ + -e WHD_SCRIPTS=/scripts \ + -e HUGO_GIT_URL=https://codeberg.org/offline/future \ + offline:latest +``` + +## License + +The following starter was made by [@adz](https://adz.garden) for [offline.place](https://offline.place) with the following license: + +``` +UNIVERSAL PUBLIC DOMAIN LICENSE + +This software and everything else in the universe is in the public domain. Ideas are not property. +``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d7730e2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +version: '3' + +volumes: + html: + +services: + nginx: + image: nginx:1.25.3-alpine + container_name: offline-nginx + restart: always + volumes: + - html:/usr/share/nginx/website + - ./nginx.conf:/etc/nginx/conf.d/default.conf + ports: + - 9090:80 + + builder: + build: . + container_name: offline-builder + depends_on: + - nginx + restart: always + volumes: + - html:/home/webhookd/public + - ./scripts:/home/webhookd/scripts + - ${SSH_DIR_PATH}:/home/webhookd/.ssh:ro + environment: + - HUGO_GIT_URL=git@codeberg.org:offline/future.git + - WHD_SCRIPTS=/home/webhookd/scripts + ports: + - 8080:8080 diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..3deef4c --- /dev/null +++ b/nginx.conf @@ -0,0 +1,15 @@ +server { + listen 80; + server_name localhost; + + # This is set to the build volume of our builder container in the + # `docker-compose.yml` configuration + root /usr/share/nginx/website; + index index.html; + + location / { + # First attempt to serve request as file, then as directory, then try + # to find an index.html inside, then fall back to displaying a 404 + try_files $uri $uri/index.html =404; + } +} diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100755 index 0000000..16fa2cc --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -e + +echo "◆ Check .git repository" + +if [ -z "$HUGO_GIT_URL" ]; then + echo "△ HUGO_GIT_URL environment variable is not set" + exit 1 +fi + +if [ ! -d "$HUGO_WORKING_DIR" ]; then + echo "Clone .git repository for the first time" + git clone $HUGO_GIT_URL $HUGO_WORKING_DIR +else + echo "All good!" +fi + +cd $HUGO_WORKING_DIR + +echo "◆ Pull latest version from .git repository" + +# Force pull everything, just in case +git fetch --all +git reset --hard origin/main + +echo "◆ Build static HTML page with hugo" + +# Start building website with hugo +hugo + +# Clean the public folder without affecting what's currently served by HTTP +# server +rm -rf $HUGO_PUBLIC_DIR/* +cp -r $HUGO_WORKING_DIR/public/* $HUGO_PUBLIC_DIR +rm -rf $HUGO_WORKING_DIR/public/* + +echo "▷ Sucessfully built new website!"