2 @documentencoding UTF-8
8 GoCheese is Python private package repository and caching proxy.
10 It serves two purposes:
13 @item proxying and caching of missing packages from upstream
14 @url{https://pypi.org/, PyPI}, conforming to
15 @url{https://www.python.org/dev/peps/pep-0503/, PEP-0503}
16 (Simple Repository API)
17 @item hosting of private locally uploaded packages, conforming to
18 @url{https://warehouse.pypa.io/api-reference/legacy/, Warehouse Legacy API}
21 Initially it was created as a fork of
22 @url{https://github.com/c4s4/cheeseshop, cheeseshop},
23 but nearly all the code was rewritten. It has huge differences:
26 @item proxying and caching of missing packages, including GPG signatures
27 @item @url{https://pythonwheels.com/, Wheel} uploading support
28 @item atomic packages store on filesystem
29 @item SHA256-checksummed packages: storing checksums, giving them back,
30 verifying stored files integrity, verifying checksum of uploaded
32 @item graceful HTTP-server shutdown
33 @item no YAML configuration, just command-line arguments
34 @item no package overwriting ability (as PyPI does too)
37 Also it contains @file{pyshop2packages.sh} migration script for
38 converting @url{https://pypi.org/project/pyshop/, Pyshop} database into
39 GoCheese one, including private packages.
41 GoCheese is free software, licenced under
42 @url{https://www.gnu.org/licenses/gpl-3.0.html, GNU GPLv3}:
43 see the file COPYING for copying conditions.
47 * Password authentication: Passwords.
49 * Storage format: Storage.
55 To use it for download purposes, just configure your @file{pip.conf}:
59 index-url = http://gocheese.host:8080/simple/
62 @option{-refresh} URL (@code{/simple/} by default) automatically
63 refreshes metainformation (available versions and their checksums)
64 from the upstream, when queried for package directory listing.
65 @option{-norefresh} prevents upstream queries.
67 @option{-gpgupdate} is useful mainly for migrated for Pyshop migrated
68 repositories. It forces GPG signature files downloading for all existing
71 You can upload packages to it with @url{https://pypi.org/project/twine/, twine}:
75 --repository-url http://gocheese.host:8080/simple/ \
77 --password foo dist/tarball.tar.gz
80 Or you can store it permanently in @file{.pypirc}:
84 repository: https://gocheese.host/simple/
89 If @command{twine} sends SHA256 checksum in the request, then uploaded
90 file is checked against it.
93 @unnumbered Password authentication
95 Password authentication is required for packages uploading.
96 You have to store your authentication data in @option{-passwd} file in
100 username:hashed-password
103 Empty lines and having @verb{|#|} at the beginning are skipped.
105 Supported hashing algorithms are:
109 @item @url{https://www.argon2i.com/, Argon2i} (recommended one!)
110 To get Argon2i hashed-password you can use any of following tools:
112 @item @url{https://github.com/balakhonova/argon2i,
113 go get github.com/balakhonova/argon2i} (Go)
114 @item @url{https://github.com/p-h-c/phc-winner-argon2} (C)
116 Example user @code{foo} with password @code{bar} can have the
117 following password file entry:
120 foo:$argon2i$v=19$m=32768,t=3,p=4$OGU5MTM3YjVlYzQwZjhkZA$rVn53v6Ckpf7WH0676ZQLr9Hbm6VH3YnL6I9ONJcIIU
124 You can use your operating system tools:
128 $ echo -n "password" | sha256
130 # GNU/Linux-based systems
131 $ echo -n "password" | sha256sum
133 Example user @code{foo} with password @code{bar} will have the
134 following password file entry:
137 foo:$sha256$fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
142 You can refresh passwords by sending @code{SIGHUP} signal to the working daemon:
145 $ pkill -HUP gocheese
146 $ kill -HUP `pidof gocheese`
149 Before refreshing it's recommended to check @option{-passwd} file with
150 @option{-passwd-check} option to prevent daemon failure.
153 @unnumbered TLS support
155 You can enable TLS support by specifying PEM-encoded X.509 certificate
156 and private key files. Go's TLS implementation supports TLS 1.3, HTTP/2
157 negotiation, Keep-Alives, modern ciphersuites and ECC.
159 For example generate some self-signed certificate using GnuTLS toolset:
162 $ certtool --generate-privkey --ecc --outfile prv.pem
163 $ cert_template=`mktemp`
164 $ echo cn=gocheese.host > $cert_template
166 --generate-self-signed \
167 --load-privkey=prv.pem \
168 --template $cert_template \
171 $ gocheese -tls-cert cert.pem -tls-key prv.pem [...]
175 @unnumbered Storage format
177 Root directory has the following hierarchy:
182 | +- public-package-0.1.tar.gz.sha256
183 | +- public-package-0.2.tar.gz
184 | +- public-package-0.2.tar.gz.asc
185 | +- public-package-0.2.tar.gz.sha256
188 | +- private-package-0.1.tar.gz
189 | +- private-package-0.1.tar.gz.sha256
193 Each directory is a package name. When you try to list non existent
194 directory contents (you are downloading package you have not seen
195 before), then GoCheese will download information about package's
196 versions with checksums and write them in corresponding @file{.sha256}
197 files. However no package package tarball is downloaded.
199 When you request for particular package version, then its tarball is
200 downloaded and verified against the checksum. For example in the root
201 directory above we have downloaded only @file{public-package-0.2}.
202 If upstream has corresponding @file{.asc} file, then it also will be
205 Private packages contain @file{.internal} file, indicating that it must
206 not be asked in PyPI if required version is missing. You have to create