hackage-repo-tool: Manage secure file-based package repositories

[ bsd3, distribution, program ] [ Propose Tags ] [ Report a vulnerability ]

This utility can be used to manage secure file-based package repositories (creating TUF metadata as well as a Hackage index tarball) which can be used by clients such as cabal-install. Currently it also provides various lower level utilities for creating and signing TUF files.

This is part of the Hackage Security infrastructure.


[Skip to Readme]

Flags

Automatic Flags
NameDescriptionDefault
cabal-syntax

Are we using Cabal-syntax?

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.1.0.0, 0.1.0.1, 0.1.1, 0.1.1.1, 0.1.1.2, 0.1.1.3, 0.1.1.4
Change log ChangeLog.md
Dependencies base (>=4.11 && <4.21), bytestring (>=0.10.8.2 && <0.13), Cabal (>=2.2.0.1 && <2.6 || >=3.0 && <3.7), Cabal-syntax (<3.14), directory (>=1.3.1.5 && <1.4), filepath (>=1.4.2 && <1.6), hackage-security (>=0.6 && <0.7), microlens (>=0.4.9.1 && <0.5), network (>=2.6 && <3.3), network-uri (>=2.6 && <2.7), optparse-applicative (>=0.13 && <0.19), tar (>=0.5 && <0.7), time (>=1.8.0.2 && <1.15), unix (>=2.7.2.2 && <2.9), zlib (>=0.6 && <0.8) [details]
Tested with ghc ==9.10.0, ghc ==9.8.2, ghc ==9.6.4, ghc ==9.4.8, ghc ==9.2.8, ghc ==9.0.2, ghc ==8.10.7, ghc ==8.8.4, ghc ==8.6.5, ghc ==8.4.4
License BSD-3-Clause
Copyright Copyright 2015 Well-Typed LLP
Author Edsko de Vries
Maintainer cabal-devel@haskell.org
Category Distribution
Home page https://github.com/haskell/hackage-security
Bug tracker https://github.com/haskell/hackage-security/issues
Source repo head: git clone https://github.com/haskell/hackage-security.git
Uploaded by AndreasAbel at 2024-04-16T11:58:34Z
Distributions
Reverse Dependencies 1 direct, 0 indirect [details]
Executables hackage-repo-tool
Downloads 5451 total (15 in the last 30 days)
Rating 2.0 (votes: 1) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs pending
Build status unknown [no reports yet]

Readme for hackage-repo-tool-0.1.1.4

[back to package description]

hackage-repo-tool: Manage secure file-based package repositories

Please refer to the package description for an overview of hackage-repo-tool, TUF and hackage-security.

Setting up a secure file-based repo

A file-based repository (as opposed to one running the actual Hackage software) is much easier to set up and will suffice for many purposes. Note that such a local file-based package repository can be turned into a remotely accessible secure package repository by any HTTP server supporting static file serving such as Nginx or Apache httpd.

  1. Create a directory ~/my-secure-repo containing a single subdirectory ~/my-secure-repo/package. Put whatever packages you want to make available from your repo in this subdirectory. At this point your repository might look like

    ~/my-secure-repo/package/basic-sop-0.1.0.5.tar.gz
    ~/my-secure-repo/package/generics-sop-0.1.1.1.tar.gz
    ~/my-secure-repo/package/generics-sop-0.1.1.2.tar.gz
    ~/my-secure-repo/package/json-sop-0.1.0.4.tar.gz
    ~/my-secure-repo/package/lens-sop-0.1.0.2.tar.gz
    ~/my-secure-repo/package/pretty-sop-0.1.0.1.tar.gz
    ~/my-secure-repo/package/HsYAML-0.2.1.0.tar.gz
    

    (Due to #174 this folder must contain at least one package tarball or hackage-repo-tool will fail in non-obvious ways)

    Note the flat directory structure: different packages and different versions of those packages all live in the one directory.

  2. Create public and private keys:

    # hackage-repo-tool create-keys \
                        --keys ~/my-private-keys
    

    This will create a directory structure such as

    ~/my-private-keys/mirrors/id01.private
    ~/my-private-keys/mirrors/..
    ~/my-private-keys/root/id04.private
    ~/my-private-keys/root/..
    ~/my-private-keys/snapshot/id07.private
    ~/my-private-keys/target/id08.private
    ~/my-private-keys/target/..
    ~/my-private-keys/timestamp/id11.private
    

    containing keys for all the various TUF roles.

    Note that these keys are stored outside of the repository proper.

  3. Create the initial TUF metadata and construct an index using

    # hackage-repo-tool bootstrap \
                        --repo ~/my-secure-repo \
                        --keys ~/my-private-keys
    

    This will create a directory ~/my-secure-repo/index containing the .cabal files (extracted from the package tarballs) and TUF metadata for all packages

    ~/my-secure-repo/index/basic-sop/0.1.0.5/basic-sop.cabal
    ~/my-secure-repo/index/basic-sop/0.1.0.5/package.json
    ~/my-secure-repo/index/generics-sop/0.1.1.1/generics-sop.cabal
    ~/my-secure-repo/index/generics-sop/0.1.1.1/package.json
    ...
    

    and package the contents of that directory up as the index tarball ~/my-secure-repo/00-index.tar.gz; it will also create the top-level metadata files

    ~/my-secure-repo/mirrors.json
    ~/my-secure-repo/root.json
    ~/my-secure-repo/snapshot.json
    ~/my-secure-repo/timestamp.json
    
  4. The timestamp and snapshot are valid for three days, so you will need to resign these files regularly using

    # hackage-repo-tool update \
                        --repo ~/my-secure-repo \
                        --keys ~/my-private-keys
    

    You can use the same command whenever you add any additional packages to your repository.

  5. If you now make this directory available (for instance, by pointing Apache httpd at it) you'll be able to use cabal to access it remotely by defining an appropriate repository stanza:

    repository my-secure-repo
      url: http://packages.example.org/
      secure: True
      root-keys: 2ae741f4c4a5f70ed6e6c48762e0d7a493d8dd265e9cbc6c4037dfc7ceaec70e
                 32d3db5b4403935c0baf52a2bcb05031784a971ee2d43587288776f2e90609db
                 eed36d2bb15f94628221cde558e99c4e1ad36fd243fe3748e1ee7ad00eb9d628
      key-threshold: 2
    

    Note that the keys in example above must be replaced: You need to copy the root key IDs from your generated root.json file (or you can set key-threshold to 0 if you're aware of the security implications)