From fa48f084eef99af81282ef9499fb56c67380c4a1 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 23 Sep 2021 23:06:57 +0300 Subject: [PATCH] Move documentation to doc/ --- clean.do | 2 +- doc/.gitignore | 1 + doc/clean.do | 1 + download.texi => doc/download.texi | 12 +- gocheese.info.do => doc/gocheese.info.do | 6 +- doc/index.texi | 84 ++++++++ install.texi => doc/install.texi | 2 +- doc/passwords.texi | 61 ++++++ doc/storage.texi | 44 ++++ style.css => doc/style.css | 0 doc/tls.texi | 21 ++ doc/usage.texi | 46 ++++ www.do => doc/www.do | 6 +- gocheese.texi | 256 ----------------------- 14 files changed, 272 insertions(+), 270 deletions(-) create mode 100644 doc/.gitignore create mode 100644 doc/clean.do rename download.texi => doc/download.texi (65%) rename gocheese.info.do => doc/gocheese.info.do (74%) create mode 100644 doc/index.texi rename install.texi => doc/install.texi (98%) create mode 100644 doc/passwords.texi create mode 100644 doc/storage.texi rename style.css => doc/style.css (100%) create mode 100644 doc/tls.texi create mode 100644 doc/usage.texi rename www.do => doc/www.do (86%) delete mode 100644 gocheese.texi diff --git a/clean.do b/clean.do index c1f4ca0..07e0d6a 100644 --- a/clean.do +++ b/clean.do @@ -1 +1 @@ -rm -f gocheese gocheese.info VERSION +rm -f gocheese doc/clean VERSION diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..69a5b5c --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +/gocheese.info diff --git a/doc/clean.do b/doc/clean.do new file mode 100644 index 0000000..2c778e3 --- /dev/null +++ b/doc/clean.do @@ -0,0 +1 @@ +rm -f gocheese.info diff --git a/download.texi b/doc/download.texi similarity index 65% rename from download.texi rename to doc/download.texi index 48c3118..1d85302 100644 --- a/download.texi +++ b/doc/download.texi @@ -2,27 +2,27 @@ @headitem Version @tab Date @tab Size @tab Tarball @tab SHA256 checksum @item 2.6.0 @tab 2021-01-22 @tab 58 KiB -@tab @url{gocheese-2.6.0.tar.zst, link} @url{gocheese-2.6.0.tar.zst.sig, sign} +@tab @url{download/gocheese-2.6.0.tar.zst, link} @url{gocheese-2.6.0.tar.zst.sig, sign} @tab @code{20DE75D6 903EAE4B FF1B83A2 3E91AC50 F1FA3D37 8D14829C BB130B50 020020B4} @item 2.5.0 @tab 2020-11-07 @tab 110 KiB -@tab @url{gocheese-2.5.0.tar.xz, link} @url{gocheese-2.5.0.tar.xz.sig, sign} +@tab @url{download/gocheese-2.5.0.tar.xz, link} @url{gocheese-2.5.0.tar.xz.sig, sign} @tab @code{C437AD4D 33E899F6 9DE7FC28 92F5C49C 8409913E EA26BA95 18144870 D74107B4} @item 2.4.1 @tab 2020-09-05 @tab 105 KiB -@tab @url{gocheese-2.4.1.tar.xz, link} @url{gocheese-2.4.1.tar.xz.sig, sign} +@tab @url{download/gocheese-2.4.1.tar.xz, link} @url{gocheese-2.4.1.tar.xz.sig, sign} @tab @code{8B8C5A8D 748FDB3D 875EC9DA 83744FFF 314FDDE9 22561BDE 7BBD290F 86642C0F} @item 2.4.0 @tab 2020-07-24 @tab 101 KiB -@tab @url{gocheese-2.4.0.tar.xz, link} @url{gocheese-2.4.0.tar.xz.sig, sign} +@tab @url{download/gocheese-2.4.0.tar.xz, link} @url{gocheese-2.4.0.tar.xz.sig, sign} @tab @code{6EE9A436 F415AB09 6D75FA5A D9BFBD6A 9BF9ACE2 52514802 CBFDF576 C057B2AC} @item 2.3.0 @tab 2019-12-17 @tab 101 KiB -@tab @url{gocheese-2.3.0.tar.xz, link} @url{gocheese-2.3.0.tar.xz.sig, sign} +@tab @url{download/gocheese-2.3.0.tar.xz, link} @url{gocheese-2.3.0.tar.xz.sig, sign} @tab @code{574C3641 BBDA2957 2FE57F03 98606403 4D7B2C58 44B2CFA4 0EBF9F75 E0186989} @item 2.2.0 @tab 2019-12-09 @tab 100 KiB -@tab @url{gocheese-2.2.0.tar.xz, link} @url{gocheese-2.2.0.tar.xz.sig, sign} +@tab @url{download/gocheese-2.2.0.tar.xz, link} @url{gocheese-2.2.0.tar.xz.sig, sign} @tab @code{5AA24DA6 C03C51BD 5C45CD50 AA1F19B5 6360C892 3ED86F06 D0F2B8FA 4C8CCB5B} @end multitable diff --git a/gocheese.info.do b/doc/gocheese.info.do similarity index 74% rename from gocheese.info.do rename to doc/gocheese.info.do index 8b00bd7..469a47b 100644 --- a/gocheese.info.do +++ b/doc/gocheese.info.do @@ -1,8 +1,8 @@ -redo-ifchange *.texi VERSION +redo-ifchange *.texi ../VERSION ${MAKEINFO:-makeinfo} \ - -D "VERSION `cat VERSION`" \ + -D "VERSION `cat ../VERSION`" \ --set-customization-variable SECTION_NAME_IN_TITLE=1 \ --set-customization-variable TREE_TRANSFORMATIONS=complete_tree_nodes_menus \ --set-customization-variable CLOSE_QUOTE_SYMBOL=\" \ --set-customization-variable OPEN_QUOTE_SYMBOL=\" \ - --output $3 gocheese.texi + --output $3 index.texi diff --git a/doc/index.texi b/doc/index.texi new file mode 100644 index 0000000..fe2ad4e --- /dev/null +++ b/doc/index.texi @@ -0,0 +1,84 @@ +\input texinfo +@documentencoding UTF-8 +@settitle GoCheese + +@copying +Copyright @copyright{} 2019-2021 @email{stargrave@@stargrave.org, Sergey Matveev} +@end copying + +@node Top +@top GoCheese + +GoCheese is Python private package repository and caching proxy. + +It serves two purposes: + +@itemize +@item proxying and caching of missing packages from upstream + @url{https://pypi.org/, PyPI}, conforming to + @url{https://www.python.org/dev/peps/pep-0503/, PEP-0503} + (Simple Repository API) +@item hosting of private locally uploaded packages, conforming to + @url{https://warehouse.pypa.io/api-reference/legacy/, Warehouse Legacy API} +@end itemize + +Why could you like it and how it can be better to fit your needs? + +@itemize +@item No database required. Only filesystem storage with few simple + files per package. Package deletion, renaming, making it uploadable + (private) is done with simple @command{mkdir}, @command{touch}, etc + commands +@item Just single statically compiled Go binary +@item No configuration file, but several simple command line arguments +@item Consistency (because of atomic synced operations) and integrity + (because of SHA256 checksums stored nearby) +@end itemize + +Initially it was created as a fork of +@url{https://github.com/c4s4/cheeseshop, cheeseshop}, +but nearly all the code was rewritten. It has huge differences: + +@itemize +@item Proxying and caching of missing packages, including GPG signatures +@item @url{https://pythonwheels.com/, Wheel} uploading support +@item Integrity check of proxied packages: MD5, SHA256, SHA512, BLAKE2b-256 +@item SHA256 checksums for stored packages +@item Verifying of SHA256 checksum for uploaded packages +@item Ability to authenticate upstream PyPI by its X.509 certificate's SPKI hash +@item Storing of uploaded GPG signatures +@item Secure Argon2i (or SHA256) stored passwords hashing +@item No YAML configuration, just command-line arguments +@item No package overwriting ability (as PyPI does too) +@item Graceful HTTP-server shutdown +@item Atomic packages store on filesystem +@end itemize + +Also it contains @file{contrib/pyshop2packages.sh} migration script for +converting @url{https://pypi.org/project/pyshop/, Pyshop} database into +GoCheese one, including private packages. + +GoCheese is +@url{https://www.gnu.org/philosophy/pragmatic.html, copylefted} +@url{https://www.gnu.org/philosophy/free-sw.html, free software} +licenced under @url{https://www.gnu.org/licenses/gpl-3.0.html, GNU GPLv3}. + +Please send questions, bug reports and patches to @url{gocheese@@cypherpunks.ru}. + +@insertcopying + +@menu +* Install:: +* Usage:: +* Password authentication: Passwords. +* TLS support: TLS. +* Storage format: Storage. +@end menu + +@include install.texi +@include usage.texi +@include passwords.texi +@include tls.texi +@include storage.texi + +@bye diff --git a/install.texi b/doc/install.texi similarity index 98% rename from install.texi rename to doc/install.texi index eca6699..4922b1c 100644 --- a/install.texi +++ b/doc/install.texi @@ -45,7 +45,7 @@ $ gpg --auto-key-locate wkd --locate-keys gocheese at cypherpunks dot ru @end example @item -@verbatiminclude PUBKEY.asc +@verbatiminclude ../PUBKEY.asc @end itemize diff --git a/doc/passwords.texi b/doc/passwords.texi new file mode 100644 index 0000000..18b8f6b --- /dev/null +++ b/doc/passwords.texi @@ -0,0 +1,61 @@ +@node Passwords +@unnumbered Password authentication + +Password authentication is required for packages uploading. +You have to store your authentication data in @option{-passwd} file in +following format: + +@example +username:hashed-password +@end example + +Empty lines and having @verb{|#|} at the beginning are skipped. + +Supported hashing algorithms are: + +@table @asis + +@item @url{https://www.argon2i.com/, Argon2i} (recommended one!) + To get Argon2i hashed-password you can use any of following tools: + @itemize + @item go get @url{https://github.com/balakhonova/argon2i, + github.com/balakhonova/argon2i} (Go) + @item @url{https://github.com/p-h-c/phc-winner-argon2} (C) + @end itemize + Example user @code{foo} with password @code{bar} can have the + following password file entry: + +@verbatim +foo:$argon2i$v=19$m=32768,t=3,p=4$OGU5MTM3YjVlYzQwZjhkZA$rVn53v6Ckpf7WH0676ZQLr9Hbm6VH3YnL6I9ONJcIIU +@end verbatim + +@item SHA256 + You can use your operating system tools: + +@example +# BSD-based systems: +$ echo -n "password" | sha256 + +# GNU/Linux-based systems +$ echo -n "password" | sha256sum +@end example + + Example user @code{foo} with password @code{bar} will have the + following password file entry: + +@verbatim +foo:$sha256$fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 +@end verbatim + +@end table + +You can refresh passwords by sending @code{SIGHUP} signal to the working daemon: + +@example +$ pkill -HUP gocheese +$ kill -HUP `pidof gocheese` +$ svc -h /var/service/gocheese +@end example + +Before refreshing it's recommended to check @option{-passwd} file with +@option{-passwd-check} option to prevent daemon failure. diff --git a/doc/storage.texi b/doc/storage.texi new file mode 100644 index 0000000..46e35bc --- /dev/null +++ b/doc/storage.texi @@ -0,0 +1,44 @@ +@node Storage +@unnumbered Storage format + +Root directory has the following hierarchy: + +@verbatim +root + +-- public-package + | +- public-package-0.1.tar.gz.md5 + | +- public-package-0.1.tar.gz.blake2_256 + | +- public-package-0.1.1.tar.gz.blake2_256 + | +- public-package-0.2.tar.gz + | +- public-package-0.2.tar.gz.asc + | +- public-package-0.2.tar.gz.sha256 + +-- private-package + | +- .internal + | +- private-package-0.1.tar.gz + | +- private-package-0.1.tar.gz.asc + | +- private-package-0.1.tar.gz.sha256 + |... +@end verbatim + +Each directory is a normalized package name. When you try to list non +existent directory contents (you are downloading package you have not +seen before), then GoCheese will download information about package's +versions with checksums and write them in corresponding +@file{.sha256}, @file{.blake2_256}, @file{.sha512}, @file{.md5} files. +However no package package tarball is downloaded. + +When you request for particular package version, then its tarball is +downloaded and verified against the stored checksum. But SHA256 is +forced to be stored and used later. + +For example @file{public-package} has @code{0.1} version, downloaded a +long time ago with MD5 checksum. @code{0.1.1} version is downloaded more +recently with BLAKE2b-256 checksum, also storing that checksum for +@code{0.1}. @code{0.2} version is downloaded tarball, having forced +SHA256 recalculated checksum. Also upstream has corresponding +@file{.asc} signature file. + +@file{private-package} is private package, because it contains +@file{.internal} file. It can be uploaded and queries to it are not +proxied to upstream PyPI. You have to create it manually. If you upload +GPG signature, then it will be also stored. diff --git a/style.css b/doc/style.css similarity index 100% rename from style.css rename to doc/style.css diff --git a/doc/tls.texi b/doc/tls.texi new file mode 100644 index 0000000..3ab47ef --- /dev/null +++ b/doc/tls.texi @@ -0,0 +1,21 @@ +@node TLS +@unnumbered TLS support + +You can enable TLS support by specifying PEM-encoded X.509 certificate +and private key files. Go's TLS implementation supports TLS 1.3, HTTP/2 +negotiation, Keep-Alives, modern ciphersuites and ECC. + +For example generate some self-signed certificate using GnuTLS toolset: + +@example +$ certtool --generate-privkey --ecc --outfile prv.pem +$ cert_template=`mktemp` +$ echo cn=gocheese.host > $cert_template +$ certtool \ + --generate-self-signed \ + --load-privkey=prv.pem \ + --template $cert_template \ + --outfile=cert.pem +$ rm $cert_template +$ gocheese -tls-cert cert.pem -tls-key prv.pem [...] +@end example diff --git a/doc/usage.texi b/doc/usage.texi new file mode 100644 index 0000000..e60fdd0 --- /dev/null +++ b/doc/usage.texi @@ -0,0 +1,46 @@ +@node Usage +@unnumbered Usage + +To use it for download purposes, just configure your @file{pip.conf}: + +@example +[install] +index-url = http://gocheese.host:8080/simple/ +@end example + +@option{-refresh} URL (@code{/simple/} by default) automatically +refreshes metainformation (available versions and their checksums) +from the upstream, when queried for package directory listing. +@option{-norefresh} prevents upstream queries. + +@option{-gpgupdate} is useful mainly for migrated for Pyshop migrated +repositories. It forces GPG signature files downloading for all existing +package files. + +You can upload packages to it with @url{https://pypi.org/project/twine/, twine}: + +@example +twine upload + --repository-url http://gocheese.host:8080/simple/ \ + --username spam \ + --password foo dist/tarball.tar.gz +@end example + +Or you can store it permanently in @file{.pypirc}: + +@example +[pypi] +repository: https://gocheese.host/simple/ +username: spam +password: foo +@end example + +If @command{twine} sends SHA256 checksum in the request, then uploaded +file is checked against it. + +Pay attention that you have to manually create corresponding private +package directory! You are not allowed to upload anything explicitly +flagged as internal package. + +It is advisable to run GoCheese under some kind of +@url{http://cr.yp.to/daemontools.html, daemontools}. diff --git a/www.do b/doc/www.do similarity index 86% rename from www.do rename to doc/www.do index 2f81bde..3d9c201 100644 --- a/www.do +++ b/doc/www.do @@ -1,8 +1,8 @@ -redo-ifchange *.texi VERSION +redo-ifchange *.texi ../VERSION html=gocheese.html rm -f $html/*.html ${MAKEINFO:=makeinfo} --html \ - -D "VERSION `cat VERSION`" \ + -D "VERSION `cat ../VERSION`" \ --css-include style.css \ --set-customization-variable SECTION_NAME_IN_TITLE=1 \ --set-customization-variable TREE_TRANSFORMATIONS=complete_tree_nodes_menus \ @@ -11,6 +11,6 @@ ${MAKEINFO:=makeinfo} --html \ --set-customization-variable DATE_IN_HEADER=1 \ --set-customization-variable CLOSE_QUOTE_SYMBOL=\" \ --set-customization-variable OPEN_QUOTE_SYMBOL=\" \ - -o $html gocheese.texi + -o $html index.texi find $html -type d -exec chmod 755 {} + find $html -type f -exec chmod 644 {} + diff --git a/gocheese.texi b/gocheese.texi deleted file mode 100644 index 1e9682e..0000000 --- a/gocheese.texi +++ /dev/null @@ -1,256 +0,0 @@ -\input texinfo -@documentencoding UTF-8 -@settitle GoCheese - -@copying -Copyright @copyright{} 2019-2021 @email{stargrave@@stargrave.org, Sergey Matveev} -@end copying - -@node Top -@top GoCheese - -GoCheese is Python private package repository and caching proxy. - -It serves two purposes: - -@itemize -@item proxying and caching of missing packages from upstream - @url{https://pypi.org/, PyPI}, conforming to - @url{https://www.python.org/dev/peps/pep-0503/, PEP-0503} - (Simple Repository API) -@item hosting of private locally uploaded packages, conforming to - @url{https://warehouse.pypa.io/api-reference/legacy/, Warehouse Legacy API} -@end itemize - -Why could you like it and how it can be better to fit your needs? - -@itemize -@item No database required. Only filesystem storage with few simple - files per package. Package deletion, renaming, making it uploadable - (private) is done with simple @command{mkdir}, @command{touch}, etc - commands -@item Just single statically compiled Go binary -@item No configuration file, but several simple command line arguments -@item Consistency (because of atomic synced operations) and integrity - (because of SHA256 checksums stored nearby) -@end itemize - -Initially it was created as a fork of -@url{https://github.com/c4s4/cheeseshop, cheeseshop}, -but nearly all the code was rewritten. It has huge differences: - -@itemize -@item Proxying and caching of missing packages, including GPG signatures -@item @url{https://pythonwheels.com/, Wheel} uploading support -@item Integrity check of proxied packages: MD5, SHA256, SHA512, BLAKE2b-256 -@item SHA256 checksums for stored packages -@item Verifying of SHA256 checksum for uploaded packages -@item Ability to authenticate upstream PyPI by its X.509 certificate's SPKI hash -@item Storing of uploaded GPG signatures -@item Secure Argon2i (or SHA256) stored passwords hashing -@item No YAML configuration, just command-line arguments -@item No package overwriting ability (as PyPI does too) -@item Graceful HTTP-server shutdown -@item Atomic packages store on filesystem -@end itemize - -Also it contains @file{contrib/pyshop2packages.sh} migration script for -converting @url{https://pypi.org/project/pyshop/, Pyshop} database into -GoCheese one, including private packages. - -GoCheese is -@url{https://www.gnu.org/philosophy/pragmatic.html, copylefted} -@url{https://www.gnu.org/philosophy/free-sw.html, free software} -licenced under @url{https://www.gnu.org/licenses/gpl-3.0.html, GNU GPLv3}. - -Please send questions, bug reports and patches to @url{gocheese@@cypherpunks.ru}. - -@insertcopying - -@menu -* Install:: -* Usage:: -* Password authentication: Passwords. -* TLS support: TLS. -* Storage format: Storage. -@end menu - -@include install.texi - -@node Usage -@unnumbered Usage - -To use it for download purposes, just configure your @file{pip.conf}: - -@example -[install] -index-url = http://gocheese.host:8080/simple/ -@end example - -@option{-refresh} URL (@code{/simple/} by default) automatically -refreshes metainformation (available versions and their checksums) -from the upstream, when queried for package directory listing. -@option{-norefresh} prevents upstream queries. - -@option{-gpgupdate} is useful mainly for migrated for Pyshop migrated -repositories. It forces GPG signature files downloading for all existing -package files. - -You can upload packages to it with @url{https://pypi.org/project/twine/, twine}: - -@example -twine upload - --repository-url http://gocheese.host:8080/simple/ \ - --username spam \ - --password foo dist/tarball.tar.gz -@end example - -Or you can store it permanently in @file{.pypirc}: - -@example -[pypi] -repository: https://gocheese.host/simple/ -username: spam -password: foo -@end example - -If @command{twine} sends SHA256 checksum in the request, then uploaded -file is checked against it. - -Pay attention that you have to manually create corresponding private -package directory! You are not allowed to upload anything explicitly -flagged as internal package. - -It is advisable to run GoCheese under some kind of -@url{http://cr.yp.to/daemontools.html, daemontools}. - -@node Passwords -@unnumbered Password authentication - -Password authentication is required for packages uploading. -You have to store your authentication data in @option{-passwd} file in -following format: - -@example -username:hashed-password -@end example - -Empty lines and having @verb{|#|} at the beginning are skipped. - -Supported hashing algorithms are: - -@table @asis - -@item @url{https://www.argon2i.com/, Argon2i} (recommended one!) - To get Argon2i hashed-password you can use any of following tools: - @itemize - @item go get @url{https://github.com/balakhonova/argon2i, - github.com/balakhonova/argon2i} (Go) - @item @url{https://github.com/p-h-c/phc-winner-argon2} (C) - @end itemize - Example user @code{foo} with password @code{bar} can have the - following password file entry: - -@verbatim -foo:$argon2i$v=19$m=32768,t=3,p=4$OGU5MTM3YjVlYzQwZjhkZA$rVn53v6Ckpf7WH0676ZQLr9Hbm6VH3YnL6I9ONJcIIU -@end verbatim - -@item SHA256 - You can use your operating system tools: - -@example -# BSD-based systems: -$ echo -n "password" | sha256 - -# GNU/Linux-based systems -$ echo -n "password" | sha256sum -@end example - - Example user @code{foo} with password @code{bar} will have the - following password file entry: - -@verbatim -foo:$sha256$fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 -@end verbatim - -@end table - -You can refresh passwords by sending @code{SIGHUP} signal to the working daemon: - -@example -$ pkill -HUP gocheese -$ kill -HUP `pidof gocheese` -$ svc -h /var/service/gocheese -@end example - -Before refreshing it's recommended to check @option{-passwd} file with -@option{-passwd-check} option to prevent daemon failure. - -@node TLS -@unnumbered TLS support - -You can enable TLS support by specifying PEM-encoded X.509 certificate -and private key files. Go's TLS implementation supports TLS 1.3, HTTP/2 -negotiation, Keep-Alives, modern ciphersuites and ECC. - -For example generate some self-signed certificate using GnuTLS toolset: - -@example -$ certtool --generate-privkey --ecc --outfile prv.pem -$ cert_template=`mktemp` -$ echo cn=gocheese.host > $cert_template -$ certtool \ - --generate-self-signed \ - --load-privkey=prv.pem \ - --template $cert_template \ - --outfile=cert.pem -$ rm $cert_template -$ gocheese -tls-cert cert.pem -tls-key prv.pem [...] -@end example - -@node Storage -@unnumbered Storage format - -Root directory has the following hierarchy: - -@verbatim -root - +-- public-package - | +- public-package-0.1.tar.gz.md5 - | +- public-package-0.1.tar.gz.blake2_256 - | +- public-package-0.1.1.tar.gz.blake2_256 - | +- public-package-0.2.tar.gz - | +- public-package-0.2.tar.gz.asc - | +- public-package-0.2.tar.gz.sha256 - +-- private-package - | +- .internal - | +- private-package-0.1.tar.gz - | +- private-package-0.1.tar.gz.asc - | +- private-package-0.1.tar.gz.sha256 - |... -@end verbatim - -Each directory is a normalized package name. When you try to list non -existent directory contents (you are downloading package you have not -seen before), then GoCheese will download information about package's -versions with checksums and write them in corresponding -@file{.sha256}, @file{.blake2_256}, @file{.sha512}, @file{.md5} files. -However no package package tarball is downloaded. - -When you request for particular package version, then its tarball is -downloaded and verified against the stored checksum. But SHA256 is -forced to be stored and used later. - -For example @file{public-package} has @code{0.1} version, downloaded a -long time ago with MD5 checksum. @code{0.1.1} version is downloaded more -recently with BLAKE2b-256 checksum, also storing that checksum for -@code{0.1}. @code{0.2} version is downloaded tarball, having forced -SHA256 recalculated checksum. Also upstream has corresponding -@file{.asc} signature file. - -@file{private-package} is private package, because it contains -@file{.internal} file. It can be uploaded and queries to it are not -proxied to upstream PyPI. You have to create it manually. If you upload -GPG signature, then it will be also stored. - -@bye -- 2.44.0