Installer gitrust comme service systemd (binaire natif)

Objectifs

À la fin de ce tutoriel, vous saurez :

  • O1. Créer un utilisateur système gitrust dédié et structurer l'arborescence /opt/gitrust
  • O2. Configurer PostgreSQL pour gitrust et vérifier la connexion
  • O3. Écrire et activer un fichier gitrust.service avec durcissement systemd
  • O4. Démarrer gitrust et confirmer que le serveur HTTP et SSH répondent

Pré-requis

  • Technique : Debian 12 ou Ubuntu 22.04 LTS (ou dérivé) ; accès root ou sudo ; curl, rsync, psql installés ; Docker non requis (c'est précisément l'alternative binaire natif)
  • Pédagogique : Tutoriel 01-installation-docker lu ou notions équivalentes d'administration Linux
  • Temps estimé : ~45 minutes

Vue d'ensemble

L'installation binaire natif place gitrust comme un service systemd classique, au même titre que nginx ou PostgreSQL. Il n'y a aucun conteneur : le binaire Rust s'exécute directement sous un utilisateur système dédié, avec un durcissement systemd (PrivateTmp, ProtectSystem, NoNewPrivileges).

graph LR
    A[Binaire gitrust
/opt/gitrust/gitrust] -->|ExecStart| B[systemd unit
gitrust.service] B -->|User=gitrust| C[Utilisateur système
gitrust] C -->|R/W| D[/opt/gitrust/data
repos + clé SSH] A -->|DATABASE_URL| E[PostgreSQL :5432] A -->|:4000| F[Navigateur / nginx] A -->|:2222| G[Client Git SSH]

Modèle mental : pensez à gitrust comme à nginx — un processus unique, lancé par systemd, propriétaire de ses données, sans jamais tourner en root.

Étape 1 : Créer l'utilisateur et l'arborescence

Créez un utilisateur système sans shell de login ni répertoire home personnel :

sudo useradd \
  --system \
  --home-dir /opt/gitrust \
  --shell /usr/sbin/nologin \
  --comment "Gitrust service" \
  gitrust

Créez l'arborescence de travail :

sudo mkdir -p /opt/gitrust/data/repos
sudo mkdir -p /opt/gitrust/static
sudo chown -R gitrust:gitrust /opt/gitrust
sudo chmod 750 /opt/gitrust

Sortie attendue (vérification) :

$ ls -la /opt/gitrust/
total 20
drwxr-x--- 4 gitrust gitrust 4096 ...
drwxr-xr-x 3 gitrust gitrust 4096 ...  data/
drwxr-xr-x 2 gitrust gitrust 4096 ...  static/

Checkpoint O1 : id gitrust doit retourner une ligne avec uid=NNN(gitrust) gid=NNN(gitrust). Si la commande échoue, relisez l'étape 1.

Étape 2 : Installer PostgreSQL et créer la base gitrust

Installez PostgreSQL si ce n'est pas fait :

sudo apt-get update
sudo apt-get install -y postgresql postgresql-contrib
sudo systemctl enable --now postgresql

Créez l'utilisateur et la base de données :

sudo -u postgres psql <<'SQL'
CREATE USER gitrust WITH PASSWORD 'CHOISIR_UN_MOT_DE_PASSE_FORT';
CREATE DATABASE gitrust OWNER gitrust;
GRANT ALL PRIVILEGES ON DATABASE gitrust TO gitrust;
SQL

Vérifiez la connexion :

psql "postgres://gitrust:CHOISIR_UN_MOT_DE_PASSE_FORT@localhost:5432/gitrust" \
  -c "SELECT version();"

Sortie attendue :

                                                  version
------------------------------------------------------------------------------------------------------------
 PostgreSQL 15.x on x86_64-pc-linux-gnu, ...
(1 row)

Checkpoint O2 : Si psql retourne version(), la base est accessible. Conservez le mot de passe PostgreSQL pour l'étape suivante.

Étape 3 : Déployer le binaire gitrust

Sur votre machine de développement (ou sur le serveur si vous compilez localement) :

# Depuis la racine du dépôt gitrust
cargo build --release

Puis transférez vers le serveur :

# Depuis la machine de développement
rsync -avz target/release/gitrust  user@VOTRE_SERVEUR:/opt/gitrust/gitrust
rsync -avz static/                 user@VOTRE_SERVEUR:/opt/gitrust/static/

Sur le serveur, rendez le binaire exécutable et attribuez-le à l'utilisateur gitrust :

sudo chown gitrust:gitrust /opt/gitrust/gitrust
sudo chmod 750 /opt/gitrust/gitrust
sudo chown -R gitrust:gitrust /opt/gitrust/static/

Alternative : si vous utilisez deployment/deploy.sh (fourni dans le dépôt source), il effectue les étapes 1 à 5 automatiquement. Ce tutoriel décompose les étapes pour que vous compreniez ce que le script fait.

Étape 4 : Créer le fichier de configuration .env

Créez /opt/gitrust/.env avec les valeurs minimales de production :

sudo -u gitrust tee /opt/gitrust/.env <<'EOF'
# === BASE DE DONNÉES ===
DATABASE_URL=postgres://gitrust:CHOISIR_UN_MOT_DE_PASSE_FORT@localhost:5432/gitrust

# === SERVEUR HTTP ===
SERVER_HOST=127.0.0.1
SERVER_PORT=4000
RUST_LOG=info

# === SERVEUR SSH ===
SSH_PORT=2222
SSH_LISTEN_ADDR=0.0.0.0
SSH_HOST_KEY_PATH=/opt/gitrust/data/ssh_host_ed25519_key
SSH_PUBLIC_HOST=VOTRE_DOMAINE_OU_IP

# === DÉPÔTS GIT ===
GIT_REPOS_BASE_PATH=/opt/gitrust/data/repos

# === FICHIERS STATIQUES ===
STATIC_FILES_PATH=/opt/gitrust/static

# === JWT (OBLIGATOIRE — générer avec : openssl rand -hex 64) ===
JWT_SECRET=REMPLACER_PAR_OPENSSL_RAND_HEX_64
JWT_EXPIRATION_MINUTES=15
JWT_ISSUER=gitrust

# === SESSIONS ===
SESSION_TIMEOUT_MINUTES=30
SESSION_BACKEND=seaorm

# === COOKIES ===
COOKIE_SECURE=true
COOKIE_SAME_SITE=Lax
APP_DEBUG=false

# === ADMIN INITIAL ===
ADMIN_USERNAME=admin
ADMIN_EMAIL=admin@VOTRE_DOMAINE
ADMIN_PASSWORD=REMPLACER_PAR_MOT_DE_PASSE_FORT

# === EMAIL (optionnel au démarrage initial, configurer ensuite) ===
# SMTP_HOST=smtp.example.com
# SMTP_PORT=587
EMAIL_BASE_URL=https://VOTRE_DOMAINE
EOF

Sécurisez le fichier (il contient des secrets) :

sudo chmod 600 /opt/gitrust/.env
sudo chown gitrust:gitrust /opt/gitrust/.env

Générez le vrai secret JWT :

openssl rand -hex 64

Copiez la sortie et remplacez REMPLACER_PAR_OPENSSL_RAND_HEX_64 dans /opt/gitrust/.env.

Checkpoint : sudo -u gitrust stat /opt/gitrust/.env doit afficher Mode: 0600 et Uid: gitrust.

Étape 5 : Créer le fichier gitrust.service

Créez le fichier d'unité systemd :

sudo tee /etc/systemd/system/gitrust.service <<'EOF'
[Unit]
Description=Gitrust - Self-hosted Git platform
Documentation=https://demo.gitrust.eu/docs/
After=network.target postgresql.service
Requires=postgresql.service

[Service]
Type=simple
User=gitrust
Group=gitrust
WorkingDirectory=/opt/gitrust
EnvironmentFile=/opt/gitrust/.env
ExecStart=/opt/gitrust/gitrust
Restart=on-failure
RestartSec=5
TimeoutStartSec=30
TimeoutStopSec=30

# --- Durcissement systemd ---
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true

# Répertoires en écriture autorisés
ReadWritePaths=/opt/gitrust/data

# Si gitrust écoute sur un port < 1024 (ex: 80) :
# AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
EOF

Rechargez systemd et activez le service :

sudo systemctl daemon-reload
sudo systemctl enable gitrust

Sortie attendue :

Created symlink /etc/systemd/system/multi-user.target.wants/gitrust.service → /etc/systemd/system/gitrust.service.

Checkpoint O3 : systemctl is-enabled gitrust doit afficher enabled.

Étape 6 : Premier démarrage et vérification

Démarrez le service :

sudo systemctl start gitrust

Attendez 3 secondes, puis vérifiez le statut :

sudo systemctl status gitrust

Sortie attendue :

● gitrust.service - Gitrust - Self-hosted Git platform
     Loaded: loaded (/etc/systemd/system/gitrust.service; enabled; vendor preset: enabled)
     Active: active (running) since ... ago
   Main PID: XXXX (gitrust)
      Tasks: N (limit: NNNN)
     Memory: NNM
        CPU: NNNms
     CGroup: /system.slice/gitrust.service
             └─XXXX /opt/gitrust/gitrust

Vérifiez que les ports répondent :

# HTTP
curl -s -o /dev/null -w "%{http_code}" http://localhost:4000/
# Attendu : 200 ou 302

# SSH (vérification du fingerprint)
ssh-keyscan -p 2222 -H localhost 2>/dev/null | head -1
# Attendu : [localhost]:2222 ssh-ed25519 AAAA...

Consultez les logs pour les migrations automatiques :

sudo journalctl -u gitrust -n 50 --no-pager

Cherchez les lignes :

INFO gitrust_core::migrations: Running migrations...
INFO gitrust_core::migrations: Applied migration m20260325_000001_create_repositories
...
INFO gitrust_core::migrations: All migrations applied successfully
INFO rustwarden_core::services::default_admin_service: Admin user 'admin' created

Checkpoint O4 : curl http://localhost:4000/ retourne du HTML (code 200 ou 302). Le service est opérationnel.

Récapitulatif

  • ✓ O1 accompli en créant l'utilisateur système gitrust et l'arborescence /opt/gitrust
  • ✓ O2 accompli en configurant PostgreSQL et en vérifiant la connexion avec psql
  • ✓ O3 accompli en rédigeant gitrust.service avec les directives de durcissement systemd
  • ✓ O4 accompli en démarrant le service et en confirmant la réponse HTTP et SSH

Et si ça ne marche pas

Symptôme Cause probable Correction
Active: failed immédiatement après start .env manquant ou mal formé ; DATABASE_URL incorrecte journalctl -u gitrust -n 30 --no-pager pour voir l'erreur exacte ; vérifier que /opt/gitrust/.env existe et que DATABASE_URL est correct
Permission denied dans les logs Répertoire data/ non accessible par l'utilisateur gitrust sudo chown -R gitrust:gitrust /opt/gitrust/data
Address already in use sur le port 4000 Un autre processus utilise le port sudo ss -tlnp | grep 4000 pour identifier le conflit
JWT_SECRET trop court / refus de démarrage Le secret JWT est la valeur d'exemple ou fait moins de 32 bytes Générer avec openssl rand -hex 64 et mettre à jour .env
Les migrations échouent (migration error) Base de données inaccessible ou droits insuffisants Vérifier DATABASE_URL et que l'utilisateur PG a GRANT ALL ON DATABASE gitrust
curl: (7) Failed to connect Le service n'est pas encore démarré ou écoute sur 127.0.0.1 uniquement Tester depuis le serveur (pas depuis l'extérieur) ; vérifier SERVER_HOST=127.0.0.1

Prochaine étape

03 — Premier démarrage : bootstrap admin, clé SSH hôte, vérification santé