From 366964345262b6f94526ae522c05814241cdbfed Mon Sep 17 00:00:00 2001 From: greg Date: Mon, 14 Apr 2025 21:31:26 +0200 Subject: [PATCH] push --- Dockerfile | 23 +++++++++++ README.md | 88 ++++++++++++++++++++++++++++++++++++++++ app/entrypoint.sh | 68 +++++++++++++++++++++++++++++++ app/generate-release.sh | 31 ++++++++++++++ app/index.html | 63 ++++++++++++++++++++++++++++ app/logo.png | Bin 0 -> 15361 bytes app/server.py | 17 ++++++++ compose.yml | 10 +++++ 8 files changed, 300 insertions(+) create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 app/entrypoint.sh create mode 100755 app/generate-release.sh create mode 100644 app/index.html create mode 100644 app/logo.png create mode 100644 app/server.py create mode 100644 compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..991c08c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM python:3.11-slim + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + gnupg \ + dpkg-dev \ + curl \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /workspace + +COPY app/. . + +RUN pip install --no-cache-dir gunicorn flask + +RUN chmod +x entrypoint.sh + +EXPOSE 8000 + +CMD ["./entrypoint.sh"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..cbca380 --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# APT DEPOT + +Créer un dépôt Debian sécurisé via clé GPG pour héberger des paquets + +## CONFIGURATION + +- Editer le fichier `app/entrypoint.sh` +```sh +GPG_KEY_NAME="example" +... +EMAIL="test@exemple.com" +``` + +- Changer le port `- 8000:` dans le `compose.yml` si besoin + +- Metre les paquets dans le dossier `depot/` + +## UTILISATION + +- Démarrer le conteneur +```bash +docker compose up -d +``` + +Note: La première fois, il génère les clés GPG + +:bulb: **A chaque ajout de paquet, redémarrer le conteneur pour qu'il resigne les paquets avec la clé GPG** + +#### Utiliser le dépôt pour installer des paquets + +- Ajouter la clé du dépôt ainsi que l'adresse dans les sources: +```bash +sudo wget -O /etc/apt/trusted.gpg.d/gn-depot.asc https://deb.legaragenumerique.fr/pgp-key.public + +echo 'deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/gn-depot.asc] https://deb.legaragenumerique.fr stable main' \ + | sudo tee /etc/apt/sources.list.d/gn-depot.list +``` + +- Mettre à jour les dépôts: +```bash +sudo apt update +``` + +- Installer un paquet: +```bash +sudo apt install geo -y +``` + +#### Création d'un paquet + +- Structure d'un paquet Debian: +``` +paquet/ + ├── DEBIAN + │ ├── control -> description du paquet + │ ├── postinst -> script s'éxécutant après l'installation du paquet + │ └── prerm -> script s'éxécutant avant la désinstallation du paquet + └── usr + ├── bin + │ └── mon-binaire + └── share + └── applications + └── application.desktop +``` + +- Builder le paquet: +```bash +dpkg-deb --build paquet +``` + +> Output: paquet.deb + +#### Ajout d'un paquet au dépôt + +- Renommer le paquet: +```bash +mv geo.deb geo_amd64.deb +``` + +- Placer le paquet dans le dossier `depot/`: +```bash +mv geo_amd64.deb depot/ +``` + +- Redémarrer le conteneur: +```bash +docker compose down -v && docker compose up -d +``` \ No newline at end of file diff --git a/app/entrypoint.sh b/app/entrypoint.sh new file mode 100644 index 0000000..7c60901 --- /dev/null +++ b/app/entrypoint.sh @@ -0,0 +1,68 @@ +#!/bin/bash +set -e + +# Configuration +GPG_KEY_NAME="example" +KEY_PUBLIC="/workspace/apt-repo/pgp-key.public" +KEY_PRIVATE="/workspace/secret/pgp-key.private" +EMAIL="test@exemple.com" + +echo "📦 Création du dépôt APT" +mkdir -p ./apt-repo/pool/main/binary-amd64 +mkdir -p ./apt-repo/dists/stable/main/binary-amd64 + +# Génération des clés seulement si elles n'existent pas +make_keys() { + echo "🔐 Génération des clés GPG" + cat > example-pgp-key.batch < "$KEY_PUBLIC" + gpg --armor --export-secret-keys "$GPG_KEY_NAME" > "$KEY_PRIVATE" + chmod 600 $KEY_PRIVATE + cp "$KEY_PUBLIC" ./apt-repo/pgp-key.public +} + +sign_packages() { + cd ./apt-repo + dpkg-scanpackages --arch amd64 pool/ > dists/stable/main/binary-amd64/Packages + gzip -9 < dists/stable/main/binary-amd64/Packages > dists/stable/main/binary-amd64/Packages.gz + + cd dists/stable + gpg --import /workspace/secret/pgp-key.private + + echo "⚙️ Génération de Release" + /workspace/generate-release.sh > Release + + echo "🔏 Signature du Release" + gpg --default-key "$GPG_KEY_NAME" -abs < Release > Release.gpg + gpg --default-key "$GPG_KEY_NAME" --clearsign < Release > InRelease +} + +if [ ! -f "$KEY_PUBLIC" ]; then + make_keys +else + echo "✅ Clés GPG déjà présentes, génération ignorée" +fi + +echo "🚚 Copie des paquets" +cp ./depot/* ./apt-repo/pool/main/binary-amd64/ || true + +sign_packages + +# Lancement serveur +echo "🚀 Lancement du serveur Gunicorn" +cd /workspace +cp index.html logo.png apt-repo/ +gunicorn -b 0.0.0.0:8000 server:app +echo "📡 Dépôt APT disponible sur https://votre-domaine.tld" +echo "🔑 Clé publique disponible sur https://votre-domaine.tld/pgp-key.public" diff --git a/app/generate-release.sh b/app/generate-release.sh new file mode 100755 index 0000000..a1936e8 --- /dev/null +++ b/app/generate-release.sh @@ -0,0 +1,31 @@ +#!/bin/sh +set -e + +do_hash() { + HASH_NAME=$1 + HASH_CMD=$2 + echo "${HASH_NAME}:" + for f in $(find -type f); do + f=$(echo $f | cut -c3-) # remove ./ prefix + if [ "$f" = "Release" ]; then + continue + fi + echo " $(${HASH_CMD} ${f} | cut -d" " -f1) $(wc -c $f)" + done +} + +cat << EOF +Origin: Example Repository +Label: Example +Suite: stable +Codename: stable +Version: 1.0 +Architectures: amd64 arm64 arm7 +Components: main +Description: An example software repository +Date: $(date -Ru) +EOF +do_hash "MD5Sum" "md5sum" +do_hash "SHA1" "sha1sum" +do_hash "SHA256" "sha256sum" + diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000..b1b1c49 --- /dev/null +++ b/app/index.html @@ -0,0 +1,63 @@ + + + + + + Dépôt APT - Le Garage Numérique + + + +
+ + +

Bienvenue sur le dépôt APT du Garage Numérique

+

Ce dépôt vous permet d’installer facilement les paquets maintenus par Le Garage Numérique sur les distributions basées sur Debian.

+ +

Instructions d'utilisation :

+

1. Ajouter la clé publique du dépôt :

+
sudo wget -O /etc/apt/trusted.gpg.d/gn-depot.asc https://deb.legaragenumerique.fr/pgp-key.public
+ +

2. Ajouter la source du dépôt :

+
echo 'deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/gn-depot.asc] https://deb.legaragenumerique.fr stable main' \
+| sudo tee /etc/apt/sources.list.d/gn-depot.list
+ +

3. Mettre à jour les paquets :

+
sudo apt update
+ +

4. Installer le paquet souhaité (ex. geo) :

+
sudo apt install geo
+ +

Et voilà 🎉 Vous êtes prêt à utiliser notre dépôt !

+
+ + diff --git a/app/logo.png b/app/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f9bba13adc7f6217bdc191be028b764cb56a5387 GIT binary patch literal 15361 zcmZv@byQo;7cLwiNYOxPixZ?k(c&(J;4a18-QBGa9E!UahvII9;!bgQclVq3_kI7| zweGBy$g3%^TO`^=*%}wspaH+KY_r9Y_-;7g51d;df3J zxgqxjL|#}cIFSeO8pMqwQZ)dF@tfRLu( zTL3(wZB8r_A}VfE!2f-*SX&++J*2ARamcbhJTxvYj&seMwf`mtdVPKE{ra%Cx68(C zF;#G})t}uH}-m#l$=bG{3ndI@e-k62MExZyr6Qr29u}Q8OB`o*p9ly%uSPlF?zdt%(kt|sW)>F-2ndE8GPrP} z#NxBF&z??pc6PA%&V|&~Q>NX?$;p!#v{bdUj&3Vw%G9#2+_YO=Z8~)ox=nt-dc*ta zq;ac1#t-(7>FMbuOiNQUGdGjsq_SCj9y>#c+l1oET3U3sB9KVt^ikL2`RXhDEZr)- zR@W2uIqh2ejXy&}Qfqef3=A_zH<8Q^lpiB@dc)oetUhgolFFrg-FUfMJKNv4Z}~Sn zdpoOTCks2Z_V(Hs3U!M4JGj$NTeB<{P*uV zeeHSoq;btO@__|U&mL1aK5!TrA)KvTuk#i5Vu^K>x?q$)bX9Gan-NS|E*c~P-tz|| zllkH{981kHN+C%}Nl&M(XM%4J;~H8xaYquDmzQl-#^j!FFL!UxdxB3a`st$$-Vc{C zg0J_&C%33`=e1&j3F>=6FozM1_;|s`^r{VtgZ6e-hED&IY_^Kfu*u(7dOYOt}gwoYKgo*ZWC^nSUSlh5FqRL+KM(+VUcC%d`1wW6NbVt@GX zxdRj1#m(*0$B(l!GlPWc6|-Jv?QY{){P|*0ms40qBj3Gg7#UAbPG%0AvrcKheDOGK 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') +def serve_file(path): + return send_from_directory(REPO_DIR, path) + +@app.route('/') +def index(): + return send_from_directory(REPO_DIR, 'index.html') if os.path.exists(os.path.join(REPO_DIR, 'index.html')) else 'APT Repo server is running!' + +@app.route('/pgp-key.public') +def serve_public_key(): + return send_from_directory('/workspace/depot', 'pgp-key.public') diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..9f154df --- /dev/null +++ b/compose.yml @@ -0,0 +1,10 @@ +services: + depot-apt: + container_name: depot-apt + build: . + restart: always + volumes: + - ./depot:/workspace/depot + - ./secret:/workspace/secret + ports: + - "8000:8000"