Skip to content

- Git deploy: - Algemeen

Algemene Deploy Werkwijze (Push-to-Deploy via Bare Repo)

Deze methode gebruikt Git uitsluitend als transportmechanisme om een build/snapshot van een project naar de server te publiceren.

  • De ontwikkelaar bouwt lokaal.
  • Alleen de publiceerbare artefacten worden gepusht.
  • De server ontvangt de push in een bare repository en rolt deze uit naar een doelmap.
  • Er wordt geen broncode of buildtooling op de server gebruikt.

Overzicht Architectuur

Lokaal (developer machine)

~/develop/projekt            # working directory (bron + buildscript)
~/develop/projekt-publish    # alleen publiceerbare output (transport-repo)

Server

/srv/git/projekt.git         # bare repo (ontvangt pushes)
/var/opt/projekt             # live deployment directory

Aanrader: push niet direct naar /var/opt/projekt met Git. Gebruik altijd een bare repo + hook. Dat voorkomt permissie- en consistentieproblemen.


1. Server Setup

Maak de bare repository

sudo mkdir -p /srv/git
cd /srv/git
sudo git init --bare projekt.git

Zet permissies (voorbeeld met deploy group)

sudo chown -R root:deploy /srv/git/projekt.git
sudo chmod -R g+rwX /srv/git/projekt.git
sudo find /srv/git/projekt.git -type d -exec chmod g+s {} \;

Doeldirectory voor deploy

sudo mkdir -p /var/opt/projekt
sudo chown -R root:deploy /var/opt/projekt
sudo chmod -R 2775 /var/opt/projekt

2. post-receive Hook (Server)

Bestand:

/srv/git/projekt.git/hooks/post-receive

Inhoud:

#!/bin/bash
set -euo pipefail

REPO="/srv/git/projekt.git"
TARGET="/var/opt/projekt"

umask 002
TMPDIR="$(mktemp -d)"
trap 'rm -rf "$TMPDIR"' EXIT

while read -r oldrev newrev refname; do
  [[ "$refname" == "refs/heads/main" ]] || continue

  git --git-dir="$REPO" archive "$newrev" | tar -x -C "$TMPDIR"

  rsync -rl --delete --no-times --omit-dir-times \
    "$TMPDIR"/ \
    "$TARGET"/
done

Activeer:

chmod +x /srv/git/projekt.git/hooks/post-receive

3. Developer Machine Setup

VPN host alias

Voeg toe aan /etc/hosts:

10.8.0.1 vpn

Server is dan bereikbaar als:

ssh pi@vpn

4. Publish Directory Aanmaken

In de ontwikkelomgeving:

cd ~/develop
mkdir projekt-publish
cd projekt-publish

Initialiseer transport-repo:

git init
git switch -c main
git remote add stage ssh://pi@vpn:/srv/git/projekt.git

Deze repo bevat alleen deployment-bestanden.


5. Working Directory Script

In ~/develop/projekt/ komt een script dat bepaalt welke bestanden worden gedeployed.

Bijvoorbeeld: deploy.sh

#!/usr/bin/env bash
set -euo pipefail

SRC="$HOME/develop/projekt"
PUB="$HOME/develop/projekt-publish"

# Leeg publish directory (behalve .git)
find "$PUB" -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} +

# Kopieer alleen relevante artefacten
cp -r "$SRC/bin" "$PUB/"
cp -r "$SRC/config" "$PUB/"
cp "$SRC/README.md" "$PUB/"

cd "$PUB"

# Single snapshot commit (geen historie)
git checkout --orphan main 2>/dev/null || true
git reset --mixed

git add -A

git diff --cached --quiet && { echo "No changes."; exit 0; }

git commit -m "deploy $(date -u +%Y-%m-%dT%H:%M:%SZ)"

git push --force stage main

6. Deploy Uitvoeren

Vanuit de working directory:

cd ~/develop/projekt
./deploy.sh

Dit doet: 1. Selecteert relevante bestanden 2. Zet ze in projekt-publish 3. Maakt een snapshot commit 4. Force-pusht naar server 5. Server rolt automatisch uit via hook


Runtime Voorbeeld: Shiny App achter Nginx

In dit voorbeeld is projekt een Shiny applicatie die op de server wordt uitgevoerd vanuit:

/var/opt/projekt

De post-receive hook plaatst daar de laatste snapshot, waarna de runtime (bijv. R + Shiny Server of een systemd service) direct met deze bestanden werkt.

Nginx fungeert alleen als reverse proxy naar de draaiende app.

Typische rolverdeling:

Git push  →  /srv/git/projekt.git  →  export → /var/opt/projekt  →  Shiny runtime
                                                          ↑
                                                      Nginx proxy

Waarom /var/opt?

  • /opt = software geleverd door derden
  • /var/opt = variabele runtime-instanties van die software
  • Deployed apps gedragen zich als "site-specific data" van de runtime

Dit past goed bij services zoals:

  • Shiny apps
  • self-contained Python venv apps
  • statische bundles achter een appserver

Nginx (conceptueel)

Nginx kent alleen het runtime-endpoint, niet Git:

location /projekt/ {
    proxy_pass http://127.0.0.1:3838/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

Nginx leest dus nooit uit de git repo of publish directory. Alle lifecycle gebeurt via de deploy hook.


Filosofie

Deze methode behandelt Git als:

betrouwbare transportlaag + deploy trigger

Niet als versiebeheer op de server.

Alle broncontrole blijft lokaal bij de ontwikkelaar.


Voordelen

  • Geen buildtools nodig op server
  • Reproduceerbare deployments
  • Geen configuratiedrift
  • Zeer eenvoudige rollback (force push nieuwe snapshot)
  • Server blijft "dom" en stabiel

Wanneer deze methode gebruiken

Geschikt voor: - statische sites - Shiny deployments - self-contained binaries - config bundles - kleine services

Minder geschikt voor: - multi-node CI/CD pipelines - artefact registries - complexe release workflows