2 @documentencoding UTF-8
6 Copyright @copyright{} 2019-2021 @email{stargrave@@stargrave.org, Sergey Matveev}
12 GoCheese is Python private package repository and caching proxy.
14 It serves two purposes:
17 @item proxying and caching of missing packages from upstream
18 @url{https://pypi.org/, PyPI}, conforming to
19 @url{https://www.python.org/dev/peps/pep-0503/, PEP-0503}
20 (Simple Repository API)
21 @item hosting of private locally uploaded packages, conforming to
22 @url{https://warehouse.pypa.io/api-reference/legacy/, Warehouse Legacy API}
25 Why could you like it and how it can be better to fit your needs?
28 @item No database required. Only filesystem storage with few simple
29 files per package. Package deletion, renaming, making it uploadable
30 (private) is done with simple @command{mkdir}, @command{touch}, etc
32 @item Just single statically compiled Go binary
33 @item No configuration file, but several simple command line arguments
34 @item Consistency (because of atomic synced operations) and integrity
35 (because of SHA256 checksums stored nearby)
38 Initially it was created as a fork of
39 @url{https://github.com/c4s4/cheeseshop, cheeseshop},
40 but nearly all the code was rewritten. It has huge differences:
43 @item Proxying and caching of missing packages, including GPG signatures
44 @item @url{https://pythonwheels.com/, Wheel} uploading support
45 @item Integrity check of proxied packages: MD5, SHA256, SHA512, BLAKE2b-256
46 @item SHA256 checksums for stored packages
47 @item Verifying of SHA256 checksum for uploaded packages
48 @item Storing of uploaded GPG signatures
49 @item Secure Argon2i (or SHA256) stored passwords hashing
50 @item No YAML configuration, just command-line arguments
51 @item No package overwriting ability (as PyPI does too)
52 @item Graceful HTTP-server shutdown
53 @item Atomic packages store on filesystem
56 Also it contains @file{contrib/pyshop2packages.sh} migration script for
57 converting @url{https://pypi.org/project/pyshop/, Pyshop} database into
58 GoCheese one, including private packages.
61 @url{https://www.gnu.org/philosophy/pragmatic.html, copylefted}
62 @url{https://www.gnu.org/philosophy/free-sw.html, free software}
63 licenced under @url{https://www.gnu.org/licenses/gpl-3.0.html, GNU GPLv3}.
65 Please send questions, bug reports and patches to @url{gocheese@@cypherpunks.ru}.
72 * Password authentication: Passwords.
74 * Storage format: Storage.
82 To use it for download purposes, just configure your @file{pip.conf}:
86 index-url = http://gocheese.host:8080/simple/
89 @option{-refresh} URL (@code{/simple/} by default) automatically
90 refreshes metainformation (available versions and their checksums)
91 from the upstream, when queried for package directory listing.
92 @option{-norefresh} prevents upstream queries.
94 @option{-gpgupdate} is useful mainly for migrated for Pyshop migrated
95 repositories. It forces GPG signature files downloading for all existing
98 You can upload packages to it with @url{https://pypi.org/project/twine/, twine}:
102 --repository-url http://gocheese.host:8080/simple/ \
104 --password foo dist/tarball.tar.gz
107 Or you can store it permanently in @file{.pypirc}:
111 repository: https://gocheese.host/simple/
116 If @command{twine} sends SHA256 checksum in the request, then uploaded
117 file is checked against it.
119 Pay attention that you have to manually create corresponding private
120 package directory! You are not allowed to upload anything explicitly
121 flagged as internal package.
123 It is advisable to run GoCheese under some kind of
124 @url{http://cr.yp.to/daemontools.html, daemontools}.
127 @unnumbered Password authentication
129 Password authentication is required for packages uploading.
130 You have to store your authentication data in @option{-passwd} file in
134 username:hashed-password
137 Empty lines and having @verb{|#|} at the beginning are skipped.
139 Supported hashing algorithms are:
143 @item @url{https://www.argon2i.com/, Argon2i} (recommended one!)
144 To get Argon2i hashed-password you can use any of following tools:
146 @item go get @url{https://github.com/balakhonova/argon2i,
147 github.com/balakhonova/argon2i} (Go)
148 @item @url{https://github.com/p-h-c/phc-winner-argon2} (C)
150 Example user @code{foo} with password @code{bar} can have the
151 following password file entry:
154 foo:$argon2i$v=19$m=32768,t=3,p=4$OGU5MTM3YjVlYzQwZjhkZA$rVn53v6Ckpf7WH0676ZQLr9Hbm6VH3YnL6I9ONJcIIU
158 You can use your operating system tools:
162 $ echo -n "password" | sha256
164 # GNU/Linux-based systems
165 $ echo -n "password" | sha256sum
168 Example user @code{foo} with password @code{bar} will have the
169 following password file entry:
172 foo:$sha256$fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
177 You can refresh passwords by sending @code{SIGHUP} signal to the working daemon:
180 $ pkill -HUP gocheese
181 $ kill -HUP `pidof gocheese`
184 Before refreshing it's recommended to check @option{-passwd} file with
185 @option{-passwd-check} option to prevent daemon failure.
188 @unnumbered TLS support
190 You can enable TLS support by specifying PEM-encoded X.509 certificate
191 and private key files. Go's TLS implementation supports TLS 1.3, HTTP/2
192 negotiation, Keep-Alives, modern ciphersuites and ECC.
194 For example generate some self-signed certificate using GnuTLS toolset:
197 $ certtool --generate-privkey --ecc --outfile prv.pem
198 $ cert_template=`mktemp`
199 $ echo cn=gocheese.host > $cert_template
201 --generate-self-signed \
202 --load-privkey=prv.pem \
203 --template $cert_template \
206 $ gocheese -tls-cert cert.pem -tls-key prv.pem [...]
210 @unnumbered Storage format
212 Root directory has the following hierarchy:
217 | +- public-package-0.1.tar.gz.md5
218 | +- public-package-0.1.tar.gz.blake2_256
219 | +- public-package-0.1.1.tar.gz.blake2_256
220 | +- public-package-0.2.tar.gz
221 | +- public-package-0.2.tar.gz.asc
222 | +- public-package-0.2.tar.gz.sha256
225 | +- private-package-0.1.tar.gz
226 | +- private-package-0.1.tar.gz.asc
227 | +- private-package-0.1.tar.gz.sha256
231 Each directory is a normalized package name. When you try to list non
232 existent directory contents (you are downloading package you have not
233 seen before), then GoCheese will download information about package's
234 versions with checksums and write them in corresponding
235 @file{.sha256}, @file{.blake2_256}, @file{.sha512}, @file{.md5} files.
236 However no package package tarball is downloaded.
238 When you request for particular package version, then its tarball is
239 downloaded and verified against the stored checksum. But SHA256 is
240 forced to be stored and used later.
242 For example @file{public-package} has @code{0.1} version, downloaded a
243 long time ago with MD5 checksum. @code{0.1.1} version is downloaded more
244 recently with BLAKE2b-256 checksum, also storing that checksum for
245 @code{0.1}. @code{0.2} version is downloaded tarball, having forced
246 SHA256 recalculated checksum. Also upstream has corresponding
247 @file{.asc} signature file.
249 @file{private-package} is private package, because it contains
250 @file{.internal} file. It can be uploaded and queries to it are not
251 proxied to upstream PyPI. You have to create it manually. If you upload
252 GPG signature, then it will be also stored.