$ cd ../articles/

This article is also available in Polish (polski).

1. Cel

Celem niniejszego dokumentu jest przeprowadzenie administratora systemu (lub inżyniera DevOps) przez cały cykl pracy z SourceHut — od założenia konta, przez konfigurację kluczy SSH Ed25519, aż po zarządzanie wieloma repozytoriami Git. Każdy krok jest szczegółowo opisany, opatrzony przykładem, wyjaśnieniem działania, typowymi błędami i sposobem ich naprawy.

2. Wprowadzenie

SourceHut (https://git.sr.ht) to minimalistyczna, open-source’owa platforma do hostowania projektów, rozwijana przez Drew DeVaulta. W odróżnieniu od GitHuba czy GitLaba, SourceHut kładzie nacisk na:

  • prostotę i szybkość,

  • pracę w terminalu (brak zbędnego GUI),

  • użycie SSH jako jedynego protokołu uwierzytelniania (Git),

  • wsparcie dla poczty elektronicznej jako głównego kanału współpracy (patch series),

  • brak JavaScriptu w interfejsie WWW.

SourceHut nie wspiera uwierzytelniania HTTP(S) dla operacji Git — każda interakcja wymaga pary kluczy SSH. To wymuszenie nie jest przypadkowe: eliminuje całą klasę ataków związanych z hasłami i tokenami dostępu.

3. Wymagania

Zanim rozpoczniesz, upewnij się, że spełniasz następujące warunki:

  • Gentoo Linux z działającym Portage (lub inna dystrybucja, aczkolwiek przykłady opierają się na Gentoo).

  • Zainstalowany OpenSSH (zgłasza ssh -V wersję >= 9.x).

  • Zainstalowany Git (zgłasza git --version wersję >= 2.40).

  • Działające połączenie z Internetem (port 22/TCP do git.sr.ht).

  • Konto pocztowe (wymagane do rejestracji na SourceHut).

  • Przeglądarka internetowa (jednorazowo do rejestracji i dodania klucza).

3.1. Weryfikacja wstępna

$ ssh -V
OpenSSH_9.7_p1, OpenSSL 3.0.15 3 Sep 2024

$ git --version
git version 2.47.0

$ echo $SHELL
/bin/bash

Jeśli któregoś z narzędzi brakuje, zainstaluj je:

# emerge --ask dev-vcs/git net-misc/openssh

4. Krótkie omówienie technologii

4.1. SSH (Secure Shell)

SSH to protokół tunelowania, uwierzytelniania i przesyłania danych. SourceHut używa go w dwóch rolach:

  1. Uwierzytelnienie przy push/fetch do repozytorium Git.

  2. Transport danych Git (protokół git-upload-pack / git-receive-pack przez kanał SSH).

4.2. Ed25519

Ed25519 to algorytm podpisu krzywej eliptycznej zaprojektowany przez Daniela J. Bernsteina. Jest domyślnym wyborem w podręczniku, ponieważ:

  • klucze mają zaledwie 256 bitów (nawet krótsze niż RSA 4096),

  • operacje podpisu są błyskawiczne,

  • implementacja jest odporna na timing attacki,

  • OpenSSH domyślnie priorytetyzuje Ed25519 od wersji 8.9.

4.3. Git over SSH

Git nie posiada własnego protokołu uwierzytelniania — deleguje je do warstwy transportowej. W przypadku SSH oznacza to, że cała autoryzacja odbywa się po stronie serwera na podstawie klucza publicznego zapisanego w ~/.ssh/authorized_keys użytkownika na serwerze. SourceHut przechowuje klucze publiczne na swoim backendzie i mapuje je na konta użytkowników.

5. Diagram architektury

+----------------------------------------------------+
|                  Stacja robocza                    |
|  +----------------------------------------------+  |
|  | ~/.ssh/                                      |  |
|  |   id_ed25519          (klucz prywatny)       |  |
|  |   id_ed25519.pub      (klucz publiczny)      |  |
|  |   config              (konfiguracja SSH)     |  |
|  |   known_hosts         (fingerprinty serwerów)|  |
|  +----------------------------------------------+  |
|  | ~/src/                                       |  |
|  |   moj-projekt/                               |  |
|  |     .git/                                    |  |
|  |     src/                                     |  |
|  +----------------------------------------------+  |
+----------------------------------------------------+
           |                                       |
           |  TCP/22 --- SSH auth via Ed25519      |
           |  Git protocol tunelowany w SSH        |
           v                                       v
+---------------------------+    +-----------------------------+
|  git.sr.ht:22             |    |  man.sr.ht                  |
|  ~/.ssh/authorized_keys   |    |  (lista kluczy publicznych) |
|  (automatycznie           |    |                             |
|   zarządzane przez        |    |  Rejestracja,               |
|   SourceHut backend)      |    |  dodawanie/usuwanie kluczy  |
|                           |    |  przez WWW                  |
+---------------------------+    +-----------------------------+
              |
              v
+-------------------------------+
|  Repozytorium na serwerze     |
|  /srv/git/~twojanazwa/        |
|  moj-projekt.git              |
+-------------------------------+

6. Instrukcja krok po kroku

6.1. 1. Create a SourceHut Account

Otwórz przeglądarkę i przejdź pod adres:

Wypełnij formularz:

Table 1. Pole

Pole

Wartość przykładowa

Username

jan-kowalski

Email

jan@example.com

Password

(minimum 12 znaków, unikalne)

Po wysłaniu formularza na podany adres email przyjdzie link weryfikacyjny. Kliknij go — konto zostanie aktywowane.

Zrzut ekranu (opisowy)

Po zalogowaniu zobaczysz dashboard meta.sr.ht, z którego możesz przejść do poszczególnych usług: git.sr.ht (repozytoria), builds.sr.ht (CI), lists.sr.ht (listy mailingowe) itd.

6.2. 2. Generate an SSH Ed25519 Key

Nie używaj domyślnego klucza RSA/SHA-1 wygenerowanego przez ssh-keygen bez parametrów. Ed25519 jest szybszy, bezpieczniejszy i krótszy.

$ ssh-keygen -t ed25519 -C "jan@example.com" -f ~/.ssh/id_ed25519_srht

6.2.1. Parameter Reference

-t ed25519

Typ klucza. Ed25519 jest algorytmem z rodziny kryptografii krzywych eliptycznych (ECC). OpenSSH obsługuje go od wersji 6.5 (2014).

-C "jan@example.com"

Komentarz do klucza. Standardowo umieszcza się adres email. Komentarz trafia do pliku .pub i jest widoczny w authorized_keys serwera. Ułatwia identyfikację, który klucz do kogo należy.

-f ~/.ssh/id_ed25519_srht

Ścieżka pliku wyjściowego. Użycie osobnego pliku dla SourceHut (a nie domyślnego id_ed25519) pozwala na zarządzanie wieloma kluczami dla różnych serwisów.

6.2.2. Example Output

Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/janek/.ssh/id_ed25519_srht
Your public key has been saved in /home/janek/.ssh/id_ed25519_srht.pub
The key fingerprint is:
SHA256:r4ND0mF1ng3rPr1ntEx4mpl3D4t4T0b3V3r1f13d jan@example.com
The key's randomart image is:
+--[ED25519 256]--+
|      .o=+o..    |
|      .o=*o.     |
|     . .+o+      |
|      . o+ .     |
|       oS . .    |
|      . . + .    |
|       .oo+ =    |
|        +o+ X    |
|         ooB+E.  |
+----[SHA256]-----+

6.2.3. Explanation

  • Plik id_ed25519_srht — klucz prywatny. NIGDY nie udostępniaj go nikomu. Powinien mieć prawa 600 (tylko odczyt dla właściciela).

  • Plik id_ed25519_srht.pub — klucz publiczny. Możesz go swobodnie udostępniać. To ten plik wkleisz do SourceHut.

  • fingerprint (SHA256:…​) — skrót klucza publicznego. Służy do weryfikacji tożsamości serwera (w known_hosts) oraz identyfikacji klucza.

6.2.4. Passphrase

Hasło (passphrase) to dodatkowa warstwa ochrony klucza prywatnego. Jeśli klucz zostanie skradziony, bez passphrase’a jest bezużyteczny. Zaleca się stosowanie passphrase’a o długości co najmniej 12 znaków.

6.2.5. Rollback

Usunięcie plików klucza:

$ rm ~/.ssh/id_ed25519_srht ~/.ssh/id_ed25519_srht.pub

Uwaga: jeśli klucz został już dodany do SourceHut, musisz go także usunąć z ustawień konta (patrz krok 3), inaczej stracisz dostęp do repo.

6.2.6. Common Errors

Brak passphrase’a — klucz przechowywany w plaintext

Jeżeli nie podasz passphrase’a podczas ssh-keygen, klucz prywatny będzie zapisany niezaszyfrowany. Osoba, która zdobędzie dostęp do pliku, od razu może go użyć.

Solution

Po fakcie możesz dodać passphrase do istniejącego klucza:

$ ssh-keygen -p -f ~/.ssh/id_ed25519_srht
Discussion

-p — zmiana passphrase’a, -f — wskazanie pliku klucza.

6.3. 3. Add the Public Key to Your SourceHut Account

Zaloguj się na https://meta.sr.ht i przejdź do zakładki Keys (bezpośredni link: https://meta.sr.ht/keys).

Wyświetl zawartość klucza publicznego:

$ cat ~/.ssh/id_ed25519_srht.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKmJ... jan@example.com

Skopiuj całą linię (zaczyna się od ssh-ed25519 i kończy adresem email).

W interfejsie meta.sr.ht:

  1. Kliknij Add a key.

  2. W polu tekstowym wklej skopiowaną linię.

  3. Opcjonalnie nadaj etykietę (np. "Laptop osobisty").

  4. Kliknij Add.

6.3.1. Weryfikacja

Po dodaniu klucz pojawi się na liście w sekcji SSH Keys z fingerprintem i datą dodania.

6.3.2. Common Errors

Białe znaki — kopiowanie z błędami

Jeżeli skopiujesz klucz z kilkoma liniami lub dodatkowymi spacjami, SourceHut odrzuci go. Użyj cat i zaznacz dokładnie jedną linię.

PEM Key with Different Algorithm

Jeżeli wcześniej wygenerowałeś klucz RSA bez -t ed25519, plik .pub zaczyna się od ssh-rsa. To też zadziała, ale Ed25519 jest preferowany.

6.4. 4. Configure ~/.ssh/config

Plik ~/.ssh/config pozwala na precyzyjne sterowanie parametrami połączenia SSH dla poszczególnych hostów. Dla SourceHut konfiguracja pozwala wskazać konkretny klucz prywatny (ten dedykowany dla sr.ht) oraz optymalizuje ustawienia.

$ cat >> ~/.ssh/config << 'EOF'

# SourceHut - git hosting
Host git.sr.ht
    HostName        git.sr.ht
    Port            22
    User            git
    IdentityFile    ~/.ssh/id_ed25519_srht
    IdentitiesOnly yes
    PreferredAuthentications publickey
    ServerAliveInterval 60
    ServerAliveCountMax  3
EOF

6.4.1. Parameter Reference

Host git.sr.ht

Nazwa hosta w konfiguracji SSH. Wszystkie kolejne parametry dotyczą tylko połączeń, gdy użytkownik wpisze ssh git.sr.ht lub Git użyje URL ssh://git@git.sr.ht/…​.

HostName git.sr.ht

Rzeczywista nazwa DNS serwera. Może być inna niż Host, co pozwala na tworzenie aliasów (np. Host srhtHostName git.sr.ht).

Port 22

Port SSH (domyślnie 22, ale jawna deklaracja zapobiega błędom przy zmianie domyślnych ustawień w /etc/ssh/ssh_config).

User git

Nazwa użytkownika SSH. SourceHut wymaga logowania jako git — to jedyny użytkownik dostępny na serwerze. Autoryzacja odbywa się na podstawie klucza publicznego (który jest mapowany na Twoje konto).

IdentityFile ~/.ssh/id_ed25519_srht

Ścieżka do klucza prywatnego. Jeśli pominiesz tę opcję, SSH użyje domyślnych plików (id_rsa, id_ed25519, id_ecdsa) w kolejności prób. Jawna deklaracja eliminuje domyślne próbowanie.

IdentitiesOnly yes

SSH ma używać tylko kluczy jawnie wskazanych w IdentityFile dla tego hosta, ignorując klucze załadowane przez ssh-agent. Kluczowe w środowiskach, gdzie ssh-agent ma wiele kluczy i SourceHut odrzuca połączenie po kilku nieudanych próbach.

PreferredAuthentications publickey

SSH ma od razu przejść do uwierzytelniania kluczem publicznym, bez próbowania password, keyboard-interactive ani hostbased. Przyspiesza połączenie.

ServerAliveInterval 60

Wysyłaj keepalive co 60 sekund. Zapobiega zrywaniu połączenia przez firewalle i NAT, które zamykają nieaktywne sesje.

ServerAliveCountMax 3

Maksymalna liczba nieudanych prób keepalive. Po 3 minutach (60s * 3) braku odpowiedzi SSH kończy sesję.

6.4.2. File Permissions

$ chmod 600 ~/.ssh/config   # tylko właściciel: rw
$ chmod 700 ~/.ssh          # tylko właściciel: rwx
$ chmod 600 ~/.ssh/id_ed25519_srht
$ chmod 644 ~/.ssh/id_ed25519_srht.pub

6.4.3. Common Errors

IdentityFile wskazuje na nieistniejący plik

SSH zgłosi błąd:

Warning: Identity file /home/janek/.ssh/id_ed25519_srht not accessible: No such file or directory.
Solution

Sprawdź czy plik istnieje i popraw ścieżkę w config:

$ ls -la ~/.ssh/id_ed25519_srht
IdentitiesOnly yes — zbyt restrykcyjne dla ssh-agent

Jeśli używasz ssh-agent z wieloma kluczami i potrzebujesz wszystkich, usuń IdentitiesOnly yes lub skomentuj:

#    IdentitiesOnly yes

6.4.4. Rollback zmian

Usuń dodany blok z ~/.ssh/config ręcznie (edytor) lub:

$ sed -i '/^# SourceHut/,/^$/d' ~/.ssh/config

6.5. 5. Test the SSH Connection

Zanim przejdziesz do operacji Git, zweryfikuj, czy SSH łączy się prawidłowo.

$ ssh -T git@git.sr.ht

6.5.1. Description

-T

Wyłącza alokację pseudo-terminala (TTY). Nie potrzebujemy terminala — sprawdzamy tylko, czy uwierzytelnienie działa.

git@git.sr.ht

Użytkownik git, host git.sr.ht. Parametry połączenia zostaną odczytane z ~/.ssh/config (jeśli mamy zdefiniowany Host git.sr.ht).

6.5.2. Example Output (poprawne połączenie)

Hi jan-kowalski! You've successfully authenticated, but SourceHut does not provide shell access.

Serwer potwierdza Twoją tożsamość (nazwa użytkownika), po czym zamyka połączenie — SourceHut nie daje dostępu do shella.

6.5.3. Example Output (pierwsze połączenie — fingerprint serwera)

The authenticity of host 'git.sr.ht (2604:180:2::c)' can't be established.
ED25519 key fingerprint is SHA256:U7BFPNzWZBX80l7G24f7jG/4oHBoWAb7bGqYKy6vLEs.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

6.5.4. Server Fingerprint Verification

Zweryfikuj, czy fingerprint jest poprawny. Aktualny fingerprint serwera znajdziesz na stronie:

(lub w repozytorium meta.sr.ht). Przykładowo dla połączeń IPv4 i IPv6 SourceHut używa następujących kluczy:

  • SHA256:U7BFPNzWZBX80l7G24f7jG/4oHBoWAb7bGqYKy6vLEs (ED25519)

Jeśli fingerprint się zgadza, wpisz yes. Klucz zostanie zapisany w ~/.ssh/known_hosts.

6.5.5. Explanation

  • known_hosts — plik, w którym SSH przechowuje fingerprinty serwerów, z którymi nawiązałeś połączenie. Przy kolejnych połączeniach SSH porównuje fingerprint i ostrzega, jeśli się zmienił.

  • Zmiana fingerprintu może oznaczać atak MITM (Man-In-The-Middle) lub reinstalację serwera. Zawsze weryfikuj przez inny kanał.

6.5.6. Common Errors (nieudane uwierzytelnienie)

git@git.sr.ht: Permission Denied (publickey).
Causes and Solutions
  1. Klucz prywatny nie został dodany do agenta ani wskazany w ~/.ssh/config.

    • Sprawdź IdentityFile w konfiguracji.

    • Sprawdź, czy ssh-add -l pokazuje klucz.

  2. Klucz publiczny nie został dodany do SourceHut.

  3. Złe uprawnienia pliku klucza.

    • Sprawdź: ls -la ~/.ssh/id_ed25519_srht (powinno być -rw-------).

  4. Błędny User w ~/.ssh/config.

    • SourceHut wymaga User git. Użycie własnej nazwy użytkownika zakończy się błędem.

6.5.7. Rollback zmian

Jeśli dodałeś fingerprint do known_hosts przez pomyłkę, usuń linię:

$ ssh-keygen -R git.sr.ht

6.6. 6. Create a Repository on SourceHut

Przejdź do https://git.sr.ht i kliknij Create repository.

6.6.1. Formularz

Table 2. Pole

Pole

Description

Przykład

Repository name

Nazwa repozytorium (widoczna w URL)

moj-projekt

Description

Krótki opis

Narzędzie do automatyzacji backupu

Visibility

public (widoczne dla wszystkich) lub

public

unlisted (tylko z linkiem)

Default branch

Gałąź domyślna

trunk

Update method

git push (bezpośredni push)

git push

email (patch series via lists.sr.ht)

README

Dodanie pliku README (opcjonalnie)

true

License

Wybór licencji (opcjonalnie)

BSD-2-Clause

Po zatwierdzeniu otrzymasz URL repozytorium: https://git.sr.ht/~jan-kowalski/moj-projekt

i SSH URL: git@git.sr.ht:~jan-kowalski/moj-projekt

6.6.2. Update Method Options

  • git push — standardowy push przez SSH. Każdy push jest natychmiast publikowany.

  • email — zmiany przychodzą przez serie łat (patch series) na listę mailingową. SourceHut automatycznie aplikuje je po akceptacji. To domyślny workflow dla projektów wykorzystujących rozwój oparty na emailu (np. linux-kernel, git, alpine, sr.ht we własnym zakresie).

6.7. 7. Configure the Remote Repository

Po utworzeniu repozytorium na serwerze skonfiguruj lokalnego Gita.

6.7.1. Inicjalizacja lokalnego repozytorium (jeśli nie istnieje)

$ mkdir -p ~/src/moj-projekt
$ cd ~/src/moj-projekt
$ git init
Initialized empty Git repository in /home/janek/src/moj-projekt/.git/

6.7.2. Dodanie plików i pierwszy commit

$ echo "# moj-projekt" > README.md
$ git add README.md
$ git commit -m "init: dodano README"
[trunk (root-commit) a1b2c3d] init: dodano README
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

6.7.3. Dodanie zdalnego repozytorium

$ git remote add origin git@git.sr.ht:~jan-kowalski/moj-projekt
$ git remote -v
origin  git@git.sr.ht:~jan-kowalski/moj-projekt (fetch)
origin  git@git.sr.ht:~jan-kowalski/moj-projekt (push)

6.7.4. Description polecenia

git remote add origin <url>

Dodaje zdalne repozytorium o nazwie origin (konwencja — może być dowolna). origin to domyślna nazwa używana przez Git podczas push i pull, jeśli nie podano innej.

git remote -v

Wyświetla listę zdalnych repozytoriów z URL-ami. -v (verbose) pokazuje zarówno URL fetch, jak i push.

6.7.5. SourceHut URL Format

git@git.sr.ht:~jan-kowalski/moj-projekt

  • git@git.sr.ht — użytkownik git na hoście git.sr.ht.

  • ~jan-kowalski — tylda + nazwa użytkownika SourceHut. To nie jest rozwijanie ~ w katalog domowy — to konwencja SourceHut.

  • moj-projekt — nazwa repozytorium.

6.7.6. Rollback

$ git remote remove origin

6.8. 8. First Push

$ git push -u origin trunk

6.8.1. Example Output

Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 276 bytes | 276.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To git.sr.ht:~jan-kowalski/moj-projekt
 * [new branch]      trunk -> trunk
branch 'trunk' has been set up to track 'origin/trunk'.

6.8.2. Parameter Reference

-u (--set-upstream)

Ustawia gałąź zdalną jako upstream dla bieżącej gałęzi. Dzięki temu przyszłe komendy git push i git pull mogą być wywoływane bez podawania nazwy zdalnego repozytorium i gałęzi.

origin

Nazwa zdalnego repozytorium (dodana wcześniej przez git remote add).

trunk

Nazwa gałęzi lokalnej do wypchnięcia. SourceHut domyślnie używa trunk (nie master ani main).

6.8.3. Explanation

  • Git najpierw kompresuje obiekty (commity, drzewa, bloby).

  • Przesyła je przez tunel SSH.

  • Serwer aktualizuje referencję gałęzi i odpowiada potwierdzeniem.

  • branch 'trunk' has been set up to track 'origin/trunk' — Git zapisał w konfiguracji lokalnej (branch.trunk.remote = origin, branch.trunk.merge = refs/heads/trunk).

6.8.4. Common Errors

remote: Repository Not Found: ~jan-kowalski/moj-projekt
fatal: repository 'git@git.sr.ht:~jan-kowalski/moj-projekt/' not found
Causes
  1. Repozytorium nie zostało utworzone na serwerze.

  2. Nazwa użytkownika w URL jest niepoprawna.

  3. Literówka w nazwie repozytorium.

Solution

6.8.5. Rollback

Nie ma prostego "undo" dla pusha. Jeśli chcesz usunąć zdalną gałąź:

$ git push origin --delete trunk

6.9. 9. Clone the Repository

$ git clone git@git.sr.ht:~jan-kowalski/moj-projekt
Cloning into 'moj-projekt'...
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.

6.9.1. Description

git clone

Tworzy lokalną kopię zdalnego repozytorium. Automatycznie:

  1. Tworzy katalog o nazwie repozytorium.

  2. Inicjalizuje .git.

  3. Dodaje origin jako zdalne repozytorium.

  4. Pobiera (fetch) wszystkie obiekty i referencje.

  5. Tworzy lokalną gałąź trunk śledzącą origin/trunk.

  6. Odpala git checkout trunk (od wersji 2.38).

6.9.2. Klonowanie do konkretnego katalogu

$ git clone git@git.sr.ht:~jan-kowalski/moj-projekt ~/src/moj-projekt

6.9.3. Klonowanie tylko jednej gałęzi (płytkie)

$ git clone --depth 1 --branch trunk \
    git@git.sr.ht:~jan-kowalski/moj-projekt
--depth 1

Tylko ostatni commit — bez historii.

--branch trunk

Klonuje konkretną gałąź (domyślnie domyślną gałąź zdalną).

6.9.4. Rollback

Usuń sklonowany katalog:

$ rm -rf ~/src/moj-projekt

6.10. 10. Managing Multiple Repositories

SourceHut wspiera organizację pracy przez grupy repozytoriów. Każdy użytkownik może mieć dowolną liczbę repozytoriów. Dodatkowo istnieje możliwość tworzenia organizacji (teams).

6.10.1. Wiele repozytoriów w jednym projekcie

Utwórz osobne repozytorium dla każdego komponentu (backend, frontend, dokumentacja):

$ git remote add backend    git@git.sr.ht:~jan-kowalski/moj-projekt-backend
$ git remote add frontend   git@git.sr.ht:~jan-kowalski/moj-projekt-frontend
$ git remote add docs       git@git.sr.ht:~jan-kowalski/moj-projekt-docs

6.10.2. Konfiguracja wielu kluczy SSH dla różnych serwisów

Jeśli masz konta na różnych serwisach Git (SourceHut, GitHub, własny serwer), skonfiguruj ~/.ssh/config dla każdego:

# SourceHut
Host git.sr.ht
    HostName        git.sr.ht
    User            git
    IdentityFile    ~/.ssh/id_ed25519_srht
    IdentitiesOnly yes

# GitHub
Host github.com
    HostName        github.com
    User            git
    IdentityFile    ~/.ssh/id_ed25519_github
    IdentitiesOnly yes

# Własny serwer Git
Host git.example.com
    HostName        git.example.com
    Port            2222
    User            git
    IdentityFile    ~/.ssh/id_ed25519_example
    IdentitiesOnly yes

6.10.3. Description

  • Każdy Host definiuje osobny zestaw reguł.

  • SSH dopasowuje Host na podstawie nazwy wpisanej w URL (np. git@github.com dopasuje Host github.com).

  • Dzięki IdentityFile każdy serwis dostaje inny klucz — jeśli jeden klucz zostanie skompromitowany, pozostałe serwisy są bezpieczne.

6.10.4. Zarządzanie przez ~/.ssh/config z Include

Większe konfiguracje warto dzielić na pliki:

$ cat ~/.ssh/config
Include ~/.ssh/config.d/*
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

$ mkdir -p ~/.ssh/config.d
$ cat > ~/.ssh/config.d/srht << 'EOF'
Host git.sr.ht
    HostName        git.sr.ht
    User            git
    IdentityFile    ~/.ssh/id_ed25519_srht
    IdentitiesOnly yes
EOF

6.10.5. Rollback

$ rm ~/.ssh/config.d/srht

6.11. 11. Default Branch and Git Aliases

SourceHut domyślnie używa gałęzi trunk. Dla wygody skonfiguruj aliasy:

$ git config --global init.defaultBranch trunk
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.lg "log --oneline --graph --all --decorate"

6.11.1. Explanation

init.defaultBranch trunk

Ustawia domyślną gałąź dla git init na trunk (zgodnie z konwencją SourceHut).

Aliasy skracają często używane komendy.

6.12. 12. Signing Commits (SSH)

SourceHut wspiera weryfikację commitów podpisanych kluczem SSH (od Git 2.34+). Jest to prostsze niż GPG i nie wymaga infrastruktury kluczy publicznych.

6.12.1. Generowanie klucza podpisu (jeśli nie masz)

Możesz użyć istniejącego klucza Ed25519 lub wygenerować osobny:

$ ssh-keygen -t ed25519 -C "jan@example.com" -f ~/.ssh/id_ed25519_sign

6.12.2. Konfiguracja Gita

$ git config --global gpg.format ssh
$ git config --global user.signingkey ~/.ssh/id_ed25519_sign.pub
$ git config --global commit.gpgSign true

6.12.3. Description

gpg.format ssh

Git ma używać SSH (a nie GPG) do podpisywania.

user.signingkey ~/.ssh/id_ed25519_sign.pub

Ścieżka do klucza publicznego. Git odczyta klucz publiczny, ale do podpisu użyje odpowiadającego mu klucza prywatnego.

commit.gpgSign true

Każdy commit będzie domyślnie podpisany (równoważne git commit -S).

6.12.4. Dodanie klucza publicznego do SourceHut

Przejdź do ustawień https://meta.sr.ht/keys i dodaj klucz.

6.12.5. Test podpisu

$ git commit --allow-empty -m "test: podpis SSH"
$ git log --show-signature -1

6.12.6. Example Output

commit a1b2c3d4e5f6...
Good "git" signature for janek with ED25519 key SHA256:...
Author: Jan Kowalski <jan@example.com>
Date:   Mon Jul 20 12:00:00 2026 +0200

    test: podpis SSH

Good "git" signature oznacza, że podpis jest poprawny.

6.12.7. Weryfikacja na SourceHut

Po pushu podpisany commit będzie oznaczony zieloną ikonką w interfejsie WWW.

6.12.8. Common Errors

error: cannot run ssh-keygen: No such file or directory
fatal: failed to write commit signature
Przyczyna

Git nie może znaleźć ssh-keygen (wymagane do wyodrębnienia klucza do podpisu). Solution:

# emerge --ask net-misc/openssh

6.12.9. Rollback

$ git config --global --unset gpg.format
$ git config --global --unset user.signingkey
$ git config --global --unset commit.gpgSign

7. Discussion wszystkich poleceń

7.1. ssh-keygen

Narzędzie OpenSSH do generowania, zarządzania i konwersji kluczy uwierzytelniania.

Składnia
ssh-keygen [opcje] [-t typ] [-C komentarz] [-f plik_wyjściowy]
Table 3. Najważniejsze opcje

Opcja

Description

-t

Typ klucza: ed25519, rsa, ecdsa, ecdsa-sk, ed25519-sk

-C

Komentarz (zwykle email)

-f

Ścieżka pliku wyjściowego

-N

Nowy passphrase (uwaga: widoczny w historii shella)

-p

Zmiana passphrase’a istniejącego klucza

-l

Wyświetlenie fingerprintu klucza

-R

Usunięcie hosta z known_hosts

7.2. ssh

Klient SSH — program do łączenia się z serwerami SSH.

Składnia
ssh [opcje] [user@]host [komenda]
Table 4. Najważniejsze opcje

Opcja

Description

-T

Wyłączenie alokacji TTY

-v

Tryb verbose (diagnostyka połączenia)

-p

Port (jeśli inny niż 22)

-i

Plik klucza prywatnego

-o

Opcja w formacie Klucz=Wartość

7.3. git clone

Klonowanie zdalnego repozytorium do lokalnego katalogu.

Składnia
git clone [opcje] <url> [katalog-docelowy]

7.4. git remote

Zarządzanie zdalnymi repozytoriami.

Składnia
git remote [-v | --verbose]
git remote add <nazwa> <url>
git remote remove <nazwa>
git remote rename <stara> <nowa>
git remote set-url <nazwa> <nowy-url>

7.5. git push

Wysyłanie commitów do zdalnego repozytorium.

Składnia
git push [repozytorium] [gałąź]
git push -u origin trunk

7.6. git fetch

Pobieranie referencji i obiektów ze zdalnego repozytorium bez scalania.

Składnia
git fetch [repozytorium]
git fetch --all

7.7. git pull

Pobranie i scalenie zmian ze zdalnego repozytorium.

Składnia
git pull [repozytorium] [gałąź]

git pull jest równoważne git fetch + git merge FETCH_HEAD.

8. Weryfikacja poprawności

8.1. Post-Configuration Checklist

# 1. Klucz istnieje i ma poprawne uprawnienia
$ ls -la ~/.ssh/id_ed25519_srht

# 2. Klucz publiczny jest czytelny
$ cat ~/.ssh/id_ed25519_srht.pub

# 3. Konfiguracja SSH jest poprawna
$ ssh -T git@git.sr.ht
# Oczekiwane: "Hi ... You've successfully authenticated"

# 4. Zdalne repozytorium jest skonfigurowane
$ git remote -v

# 5. Push działa
$ git push -u origin trunk

# 6. Klonowanie działa (z innego katalogu, na próbę)
$ cd /tmp && git clone git@git.sr.ht:~jan-kowalski/moj-projekt && rm -rf moj-projekt

9. Diagnostyka

9.1. Increasing SSH Verbosity

Jeśli połączenie nie działa, uruchom SSH w trybie verbose:

$ ssh -vT git@git.sr.ht

Dla jeszcze większej szczegółowości:

$ ssh -vvvT git@git.sr.ht

9.1.1. Interpreting Output

Szukaj linii:

  • Authenticated to git.sr.ht ([…​]:22) — sukces.

  • Permission Denied (publickey). — brak autoryzacji.

  • Connection refused — serwer nie odpowiada (port zamknięty? firewall).

  • Connection timed out — brak routingu do serwera.

9.2. DNS Test

$ host git.sr.ht
git.sr.ht has address 78.46.77.55
git.sr.ht has IPv6 address 2604:180:2::c

9.3. Port Test

$ nc -zv git.sr.ht 22
Connection to git.sr.ht (78.46.77.55) port 22 [tcp/ssh] succeeded!

9.4. Check SSH Agent

$ ssh-add -l
The agent has no identities.

Jeśli agent nie ma kluczy, dodaj:

$ ssh-add ~/.ssh/id_ed25519_srht

10. Common Errors

10.1. Permission Denied (publickey)

Table 5. Przyczyna

Możliwa przyczyna

Solution

Klucz nie dodany do konta

Dodaj w https://meta.sr.ht/keys

Zły klucz w IdentityFile

Sprawdź ~/.ssh/config

Złe uprawnienia plików

chmod 600 dla klucza, chmod 700 dla ~/.ssh

ssh-agent z nieprawidłowym

Użyj IdentitiesOnly yes w configu

kluczem (wiele kluczy)

10.2. Repository Not Found

Table 6. Przyczyna

Możliwa przyczyna

Solution

Repozytorium nie istnieje

Utwórz na https://git.sr.ht

Literówka w URL remote

git remote set-url origin <poprawny-url>

Brak tyldy przed nazwą użytkownika

URL musi zaczynać się od git@git.sr.ht:~

Zła nazwa użytkownika

Sprawdź w prawym górnym rogu dashboardu

10.3. SSH Agent Conflict (Key Rejection)

Objaw: pomimo poprawnego klucza, SSH odrzuca połączenie po kilku próbach z różnymi kluczami. Przyczyna: ssh-agent próbuje kolejno wszystkie załadowane klucze. Jeśli któryś z nich nie jest zaakceptowany przez SourceHut, serwer może po kilku próbach zamknąć połączenie.

Solution 1: jawne wskazanie klucza
$ ssh -i ~/.ssh/id_ed25519_srht -o IdentitiesOnly=yes git@git.sr.ht
Solution 2: konfiguracja (trwałe)

Dodaj IdentitiesOnly yes w ~/.ssh/config jak w kroku 4.

10.4. Changing SourceHut Username

Jeśli zmienisz nazwę użytkownika na SourceHut:

  1. Wszystkie URL-e repozytoriów zmieniają się (musisz zaktualizować remote).

  2. Klucze SSH są nadal powiązane z kontem — nie musisz ich zmieniać.

  3. Zaktualizuj ~/.ssh/config jeśli używasz aliasów.

10.5. 100% CPU During git push (Compression)

Git domyślnie używa wielu wątków do kompresji. Na słabszym sprzęcie możesz ograniczyć:

$ git config --global pack.threads 1

11. Dobre praktyki

11.1. Key Security

  1. Nigdy nie udostępniaj klucza prywatnego. Pliki id_ed25519, id_rsa itd. są prywatne. Nie wrzucaj ich do repozytoriów, nie przesyłaj przez komunikatory, nie wklejaj do terminala na streamingu.

  2. Używaj passphrase. Klucz bez passphrase’a to jak hasło zapisane na kartce przyklejonej do monitora. Jeśli laptop zostanie skradziony, attacker ma natychmiastowy dostęp do wszystkich serwisów.

  3. Rotacja kluczy. Generuj nowy klucz co 12-24 miesiące. Stary klucz usuń z serwisów.

  4. Osobne klucze dla różnych serwisów. Nigdy nie używaj tego samego klucza do SourceHut, GitHub i firmowego serwera Git. Kompromitacja jednego serwisu nie powinna wpływać na pozostałe.

  5. Monitoruj dodane klucze. Regularnie przeglądaj listę kluczy na https://meta.sr.ht/keys. Nieznajomy klucz oznacza naruszenie konta.

11.2. Git Security

  1. Podpisuj commity. Użyj SSH signing (opisanego w kroku 12) lub GPG. Pozwala to zweryfikować, że commit pochodzi rzeczywiście od Ciebie.

  2. Nie pushuj secrets. Nigdy nie wrzucaj haseł, tokenów API ani kluczy prywatnych do repozytorium. Użyj .gitignore lub narzędzi jak git-secrets, trufflehog.

  3. Sprawdzaj przed pushem. Użyj hooków pre-push do walidacji.

11.3. Repository Organization

  1. Jedna nazwa, jeden cel. Każde repozytorium powinno mieć jasno określony zakres (jeden projekt, jeden komponent).

  2. Konwencja nazewnicza. Używaj kebab-case: moj-projekt-backend, moj-projekt-frontend.

  3. README. Każde repozytorium powinno zawierać README z opisem, instrukcją uruchomienia i budowania.

11.4. Working with SourceHut

  1. Używaj trunk zamiast master/main. SourceHut domyślnie używa trunk. Jest to zgodne z filozofią platformy.

  2. Rozważ workflow oparty na emailu. SourceHut został zaprojektowany z myślą o rozwoju przez serie łat. Lists.sr.ht i Mail zintegrowane z Gitem dają pełną kontrolę nad historią projektu.

  3. Backupuj repozytoria. SourceHut to usługa — nie traktuj jej jako jedynej kopii. Regularnie wykonuj git clone --mirror lub używaj drugiego zdalnego repozytorium jako backupu.

11.5. Repository Backup

# Mirror (pełna kopia, wszystkie gałęzie, tagi)
$ git clone --mirror git@git.sr.ht:~jan-kowalski/moj-projekt \
    /backup/moj-projekt.git

# Aktualizacja mirrora
$ cd /backup/moj-projekt.git && git fetch --all

12. Bezpieczeństwo

12.1. SSH Key Attacks

Zagrożenie

Mitigacja

Kradzież klucza prywatnego

Passphrase, szyfrowanie dysku,

ograniczone zaufanie do hosta

Atak MITM (podmiana fingerprintu)

Weryfikacja fingerprintu przez

inny kanał (HTTPS, DNS, osobisty kontakt)

Klucz pozostawiony w ssh-agent

ssh-add -D po sesji,

ssh-add -t 3600 (timeout)

Użycie słabego algorytmu

Tylko Ed25519 (RSA 4096 jako fallback)

12.2. Firewall and Network

  • SSH używa portu 22/TCP. Jeśli pracujesz za firewallem korporacyjnym, upewnij się, że ruch do git.sr.ht:22 jest dozwolony.

  • Rozważ użycie ProxyJump przez bastion host, jeśli bezpośrednie połączenie nie jest możliwe.

12.3. Monitoring Suspicious Activity

  • SourceHut wysyła powiadomienia email o nowych kluczach dodanych do konta.

  • Regularnie sprawdzaj logi SSH po stronie klienta: journalctl -u sshd (jeśli masz serwer SSH) lub ~/.ssh/known_hosts pod kątem nieznajomych wpisów.

13. Podsumowanie

Niniejszy podręcznik przeprowadził Cię przez pełny cykl pracy z SourceHut — od założenia konta, przez generowanie kluczy SSH Ed25519, konfigurację ~/.ssh/config, test połączenia, utworzenie i zarządzanie repozytoriami Git, aż po podpisywanie commitów i diagnostykę.

SourceHut różni się od popularnych platform (GitHub, GitLab) przede wszystkim:

  • obowiązkowym uwierzytelnianiem SSH,

  • minimalistycznym interfejsem,

  • priorytetyzacją poczty elektronicznej jako kanału współpracy.

Znajomość tych różnic i umiejętność poprawnej konfiguracji SSH jest kluczowa dla sprawnej pracy z tą platformą.

14. Checklista

Po rejestracji i konfiguracji
  • ✓ Konto na SourceHut utworzone i zweryfikowane

  • ✓ Klucz SSH Ed25519 wygenerowany (ssh-keygen -t ed25519)

  • ✓ Klucz publiczny dodany do https://meta.sr.ht/keys

  • ~/.ssh/config skonfigurowany (IdentityFile, IdentitiesOnly)

  • ✓ Uprawnienia plików poprawne (~/.ssh: 700, klucze: 600, .pub: 644)

  • ✓ Test połączenia SSH zaliczony (ssh -T git@git.sr.ht)

  • ✓ Repozytorium utworzone na https://git.sr.ht

  • ✓ Lokalne repozytorium zainicjalizowane (git init)

  • ✓ Zdalne repozytorium dodane (git remote add origin)

  • ✓ Pierwszy push wykonany (git push -u origin trunk)

  • ✓ Klonowanie działa (git clone)

  • ✓ Podpisywanie commitów skonfigurowane (opcjonalne)

15. Najczęstsze problemy

15.1. Cannot Log In to SourceHut

  • Sprawdź czy konto jest aktywowane (link w emailu).

  • Użyj opcji "Reset password" na https://meta.sr.ht.

  • Jeśli problem leży po stronie uwierzytelniania SSH, zacznij od ssh -vT git@git.sr.ht.

15.2. git push wymaga hasła — ale SSH nie pyta

Jeśli SourceHut pyta o hasło zamiast uwierzytelnić kluczem, prawdopodobnie używasz URL HTTP zamiast SSH. Sprawdź:

$ git remote -v

URL powinien zaczynać się od git@git.sr.ht: — nie https://.

15.3. Webhooks Not Working

SourceHut wspiera webhooki przez builds.sr.ht i listy mailingowe, ale nie ma wbudowanego systemu webhooków jak GitHub. Do automatyzacji używaj builds.sr.ht (CI/CD).

15.4. No Pull Request Support

SourceHut nie ma pull requestów w znanym z GitHub znaczeniu. Zamiast tego używa:

  • Serii łat (patch series) — wysyłasz commity przez email na listę mailingową projektu.

  • Pull request przez email — git request-pull generuje list zmian.

Alternatywnie możesz skonfigurować osobne gałęzie i pushować je do zdalnego repozytorium, a następnie poprosić maintainera o wciągnięcie zmian.

16. Dalsza lektura

17. Najlepsze praktyki produkcyjne

  1. Używaj kluczy Ed25519 z passphrasem. Żadnych kluczy RSA 2048 bez hasła. W środowisku produkcyjnym rozważ klucze na tokenach sprzętowych (FIDO2, yubikey) z ssh-keygen -t ed25519-sk.

  2. Separacja kluczy. Osobny klucz dla SourceHut, osobny dla CI, osobny dla deploymentu. W przypadku wycieku jednego klucza, strata jest ograniczona.

  3. Automatyzacja z ssh-agent z timeoutem. W skryptach CI/Cd nie przechowuj kluczy bez passphrase. Używaj ephemeral agent z:

    [source,bash]
    ----
    eval $(ssh-agent -t 3600)  # agent wygasa po 1h
    ssh-add ~/.ssh/id_ed25519_srht
    ----
  4. Regularna rotacja kluczy. W środowisku korporacyjnym ustal politykę rotacji (np. co 6 miesięcy). Automatyzuj proces skryptem.

  5. Backup mirror dla każdego repozytorium. SourceHut to usługa zewnętrzna. Utrzymuj lokalny mirror (bare repository) i regularnie synchronizuj.

  6. Monitoruj logi SSH. Skonfiguruj syslog/auditd do logowania wszystkich prób użycia kluczy SSH. Alertuj na nieudane uwierzytelnienia.

  7. Używaj ssh-audit do skanowania konfiguracji serwera. Nawet jeśli serwer jest zewnętrzny (SourceHut), warto wiedzieć, jakie algorytmy są wspierane:

    [source,bash]
    ----
    # ssh-audit git.sr.ht
    ----
  8. Nie ufaj domyślnej konfiguracji SSH. Sprawdź /etc/ssh/ssh_config pod kątem dziedziczonych ustawień. ~/.ssh/config z Host * może nadpisać globalne ustawienia.

❯ cd ../articles/