Giter VIP home page Giter VIP logo

hackage-server's Introduction

hackage-server

Build status Build status

This is the hackage-server code. This is what powers http://hackage.haskell.org, and many other private hackage instances. The master branch is suitable for general usage. Specific policy and documentation for the central hackage instance exists in the central-server branch.

Installing dependencies

hackage-server depends on libgd, zlib, and other system libraries. You'll also need libbrotli-dev for enabling tests.

You can use the Nix package manager to provide these dependencies, or install them manually.

Using the Nix package manager and provided Nix Flake

If you have the Nix package manager installed, you can build and run hackage-server without manually installing any dependencies.

This uses flake.nix, implemented with srid/haskell-flake.

There are at least three ways to use this flake.nix. Clone this repository, enter the repository directory, then choose one of these options:

nix develop

(in develop shell)
$ cabal v2-run -- hackage-server init --static-dir=datafiles

$ cabal v2-run -- hackage-server run --static-dir=datafiles --base-uri=http://127.0.0.1:8080
hackage-server: Ready! Point your browser at http://127.0.0.1:8080

Note the init command will create a new folder state in your working directory.

If you have direnv, direnv allow will load this nix develop shell automatically.

nix build

This will produce a hackage-server executable in result/.

For this executable, Hackage dependencies are not pulled from Hackage directly like usual. Hackage dependencies are provided by the Nixpkgs haskell-updates branch, and a few overrides in flake.nix.

nix run is more convenient to use than nix build.

As with nix build, Hackage dependencies are not pulled from Hackage directly like usual. See caveat above.

List the available Flake Apps with nix flake show:

$ nix flake show
...
├───apps
...
│   │   ├───hackage-build: app
│   │   ├───hackage-import: app
│   │   ├───hackage-mirror: app
│   │   └───hackage-server: app
...

Run the hackage-server App:

nix run .#hackage-server -- init --static-dir=datafiles

nix run .#hackage-server -- run --static-dir=datafiles --base-uri=http://127.0.0.1:8080

The . refers to the flake.nix in your working directory. #hackage-server refers to the App specified in that flake.nix.

hackage-server is the default App, so those commands can be shortened:

nix run . -- init --static-dir=datafiles

nix run . -- run --static-dir=datafiles --base-uri=http://127.0.0.1:8080
Not working

Please note this App cannot be run directly from GitHub like this:

nix run github:haskell/hackage-server -- init --static-dir=datafiles

nix run github:haskell/hackage-server -- run --static-dir=datafiles --base-uri=http://127.0.0.1:8080

because hackage-server expects the directories state and datafiles to exist in the working directory.

Manually

You can also install dependencies manually via your operating system's package manager.

Libgd

You'll need to do the following to get hackage-server's dependency hs-captcha (and transitively gd) to build:

  • Mac OS X

    brew install libgd
    
  • Ubuntu/Debian

    sudo apt-get update
    sudo apt-get install unzip libgd-dev
    
  • Fedora/CentOS

    sudo dnf install unzip libgd-devel
    
  • Nix/NixOS

    nix-shell --packages gd
    

libbrotli

  • Ubuntu/Debian

    sudo apt update
    sudo apt install libbrotli-dev
    
  • Fedora/CentOS

    sudo dnf install brotli-devel
    

openssl

  • Fedora/CentOS

    sudo dnf install openssl-devel

zlib

  • Mac OS X

    brew install zlib
    
  • Ubuntu/Debian

    sudo apt-get update
    sudo apt-get install zlib
    
  • Fedora/CentOS

    sudo dnf install zlib
    
  • Nix/NixOS

    nix-shell --packages zlib
    

Mac OS X

In addition to the above commands, you'll need to run

brew install pkg-config

After running the above brew install commands, you also need to update cabal.project.local with the following:

cat >> cabal.project.local <<EOF
package gd
  extra-include-dirs:
    $(echo $(brew --prefix)/Cellar/gd/*/include)
  extra-lib-dirs:
    $(echo $(brew --prefix)/Cellar/gd/*/lib)
    $(echo $(brew --prefix)/Cellar/libpng/*/lib)
    $(echo $(brew --prefix)/Cellar/jpeg-turbo/*/lib)
    $(echo $(brew --prefix)/Cellar/fontconfig/*/lib)
    $(echo $(brew --prefix)/Cellar/freetype/*/lib)

constraints:
  , HsOpenSSL +use-pkg-config
EOF

Setting up security infrastructure

Out of the box the server comes with some example keys and TUF metadata. The example keys are in example-keys/; these keys were used to create

datafiles/TUF/root.json
datafiles/TUF/mirrors.json
datafiles/TUF/timestamp.private
datafiles/TUF/snapshot.private

While these files will enable you to start the server without doing anything else, you should replace all these files before deploying your server. In the remainder of this section we will explain how to do that.

The first step is to create your own keys using the hackage-repo-tool:

hackage-repo-tool create-keys --keys /path/to/keys

Then copy over the timestamp and snapshot keys to the TUF directory:

cp /path/to/keys/timestamp/<id>.private datafiles/TUF/timestamp.private
cp /path/to/keys/snapshot/<id>.private  datafiles/TUF/snapshot.private

Create root information:

hackage-repo-tool create-root --keys /path/to/keys -o datafiles/TUF/root.json

And finally create a list of mirrors (this is necessary even if you don't have any mirrors):

hackage-repo-tool create-mirrors --keys /path/to/keys -o datafiles/TUF/mirrors.json

The create-mirrors command takes a list of mirrors as additional arguments if you do want to list mirrors.

In order for secure clients to bootstrap the root security metadata from your server, you will need to provide them with the public key IDs of your root keys; you can find these as the file names of the files created in /path/to/keys/root (as well as in the generated root.json under the signed.roles.root.keyids). An example cabal client configuration might look something like

repository my-private-hackage
  url: http://example.com:8080/
  secure: True
  root-keys: 865cc6ce84231ccc990885b1addc92646b7377dd8bb920bdfe3be4d20c707796
             dd86074061a8a6570348e489aae306b997ed3ccdf87d567260c4568f8ac2cbee
             e4182227adac4f3d0f60c9e9392d720e07a8586e6f271ddcc1697e1eeab73390
  key-threshold: 2

Note that if you elect to not use a secure client, the hackage server will not provide your client the most recent versions of packages from its index. The cabal-version:2.0 format packages are thus only available in the newer secure repository mode. See Issue #4625 for further information.

Running

cabal install

hackage-server init
hackage-server run

If you want to run the server directly from the build tree, run

cabal v2-run -- hackage-server init

once to initialise the state. After that you can run the server with

cabal v2-run -- hackage-server run --static-dir=datafiles/ --base-uri=http://127.0.0.1:8080

By default the server runs on port 8080 with the following settings:

URL:      http://localhost:8080/
username: admin
password: admin

To specify something different, see hackage-server init --help for details.

The http://127.0.0.1:8080/packages/uploaders/edit is used to add users (e.g. admin) to Uploaders group.

The server can be stopped by using Control-C.

This will save the current state and shutdown cleanly. Running again will resume with the same state.

Resetting

To reset everything, kill the server and delete the server state:

rm -rf state/

Note that the datafiles/ and state/ directories differ: datafiles is for static html, templates and other files. The state directory holds the database (using acid-state and a separate blob store).

Creating users & uploading packages

Currently there is no restriction on registering, but only an admin user can grant privileges to registered users e.g. by adding them to other groups. In particular there are groups:

  • admins http://localhost:8080/users/admins/ -- administrators can do things with user accounts like disabling, deleting, changing other groups etc.
  • trustees http://localhost:8080/packages/trustees/ -- trustees can do janitorial work on all packages
  • mirrors http://localhost:8080/packages/mirrorers/ -- for special mirroring clients that are trusted to upload packages
  • per-package maintainer groups http://localhost:8080/package/foo/maintainers -- users allowed to upload packages
  • uploaders http://localhost:8080/packages/uploaders/ -- for uploading new packages

Mirroring

There is a client program included in the hackage-server package called hackage-mirror. It's intended to run against two servers, syncing all the packages from one to the other, e.g. getting all the packages from the old hackage and uploading them to a local instance of a hackage-server.

To try it out:

  1. On the target server, add a user to the mirrorers group via http://localhost:8080/packages/mirrorers/.

  2. Create a config file that contains the source and target servers. Assuming you are cloning the packages on http://hackage.haskell.org locally, create the file servers.cfg:

    source "hackage"
      uri: http://hackage.haskell.org
      type: secure
    
    target "mirror"
      uri: http://admin:admin@localhost:8080
      type: hackage2
    
      post-mirror-hook: "shell command to execute"
    

    Recognized types are hackage2, secure and local. The target server name was displayed when you ran.

    Note, the target must not have a trailing slash, or confusion will tend to occur. Additionally, if you have ipv6 setup on the machine, you may need to replace localhost with 127.0.0.1.

    Also note that you should mirror from hackage2 or secure typically and mirror to hackage2. Only mirroring from secure will include dependency revision information.

    hackage-server run
  3. Run the client, pointing to the config file:

    hackage-mirror servers.cfg

    This will do a one-time sync, and will bail out at the first sign of trouble. You can also do more robust and continuous mirroring. Use the flag --continuous. It will sync every 30 minutes (configurable with --interval). In this mode it carries on even when some packages cannot be mirrored for some reason and remembers them so it doesn't try them again and again. You can force it to try again by deleting the state files it mentions.

hackage-server's People

Contributors

agrafix avatar aliasqli avatar andreasabel avatar aslatter avatar awasthishubh avatar batterseapower avatar bgamari avatar bitemyapp avatar brandonchinn178 avatar conklech avatar davidlazar avatar dcoutts avatar dependabot[bot] avatar dwijnand avatar edsko avatar gbaz avatar gracenotes avatar grayjay avatar hvr avatar ian-ross avatar igfoo avatar lambda-fairy avatar lemmih avatar peterbecich avatar peti avatar phadej avatar sitaochen avatar tommd avatar werehamster avatar ysangkok avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hackage-server's Issues

Make error handling less verbose

We need a nice monadic style where we can fail with e.g. internal server errors without propagating Either blah blah all over the place. See for example how we cannot currently abstract over takeRequestBody.

Reverse dependencies

This feature was implemented but is currently turned off because it used to much memory. This should be investigated, the data structured adjusted and the feature re-enabled. The number of reverse dependencies should be an important component of a package popularity/quality metric.

Have doc builder submit build report for target only

At the moment the doc builder submits build reports for all packages it builds. Since it rebuilds all dependencies for all cases, that means that for some packages we submit the same build report over and over again (the beta hackage 2 server already has 112,000 build reports, after a few days of doc building, with some packages nearly 2000 build reports).

Extend support for trustees

In addition to package maintainers, hackage trustees are people who can help curate a collection of packages. While they cannot upload new versions of packages directly, the intention is that they can edit package metadata, including adjusting dependencies to match reality. Currently the only things they can edit are package tags and upload documentation.

Figure out why we need the -threaded option

Without threaded CTRL-C handling does not work correctly:

<starting to build package X>
<notice that package X failed>
<continue with package Y>
<cabal starts to download a dependency of Y>
<CTRL-C during the download>

At this point both cabal process is interrupted, but the doc builder process is not; a subsequent CTRL-C interrupts the doc builder but now the exception handler (installed by "finally") which writes out the "failed" state does not get run. With the -threaded option this does not happen: the CTRL-C interrupts both cabal and the doc builder, and the finally handler does run. Not necessarily a problem to need -threaded, but it would be nice to understand why.

Better support for CTRL-C

When interrupting the doc builder with CTRL-C, the package currently being built will be marked as failed.

Finish package candidates

Package candidates lets you upload a "candidate" giving it a url that others can download from, and gives an opportunity for doc builders and build bots to try the package out. Once the author is satisfied then they can publish to the main package index. This feature is about 95% complete (we think).

Keep sets of tag aliases

And we should use these sets when coalescing (see #23).

With these sets we can actually have a set of tag names that all refer to the same canonical tag name; we would use this in the search feature, when we search on tags. This means we can tidy up the tags and make them useful for organising and searching since at the moment people pick different names for the same thing

Machine readable (JSON) API for all features

Many resources have json or other machine readable formats, but not all yet. See the api page (which itself has a json version). This is an easy way to contribute to the development.

Repository meta-info not properly rendered

On http://beta.hackage.haskell.org/package/system-filepath-0.4.7

The repository info is rendered as

head: bzr branch https://john-millikin.com/branches/system-filepath/0.4/
this: SourceRepo {repoKind = RepoThis, repoType = Just Bazaar, repoLocation = Just "https://john-millikin.com/branches/system-filepath/0.4/", repoModule = Nothing, repoBranch = Nothing, repoTag = Just "system-filepath_0.4.7", repoSubdir = Nothing}

of which the 2nd line is not what a user expects to see there.

Earlier IRC discussion with @dcoutts providing directions how to fix this:

< dcoutts_> hvr: dunno why it renders like that, probably a missing case in the code
< dcoutts_> hvr: see sourceRepositoryToHtml :: SourceRepo -> Html in Distribution.Server.Pages.Package
< dcoutts_> hvr: the current code expects the module, branch and tag to be empty
< dcoutts_> but that's clearly not the case here
< dcoutts_> yours has a tag
< dcoutts_> which isn't wrong, but we don't know how to render that
< dcoutts_> should be easy to fix

Some docs have broken localhost links

Some docs contain references to localhost as well as wrong URLs (some sort of cross between new and old Hackage styles), due to a (now fixed) bug in the build client. All we need to do is to delete all the docs and re-import / rebuild them.

Site visual and information design

While we have at least switched it all to use the haddock "Ocean" theme, there's a lot more that could be done by someone good at web design. The pages are currently constructed of a mixture of templates and pages generated in code. We should try to do that consistently with templates and make it easier to adjust the site. It should also be possible to do more JS stuff, rather than classic html4 POST forms.

Server messages use wrong home URL

For example:

Hackage has been upgraded to use a more secure login system. Please go to http://hackage:8081/users/htpasswd-upgrade to re-enable your account and for more details about this change.

Proposal: store updates to package descriptions with Git as backend

Hackage 2 allows some updates for the package descriptions for already uploaded package, and stores the various revisions. Could Hackage use Git as backend and push changes to a public readonly mirror somewhere? I imagine that people can easily take a look at it; and probably it would be somewhat easy, for instance, to use Git commit ids for people interested in repeatable builds.

I mentioned this today at Zurihac, but I fear I didn't explain myself clearly.

Anonymous build reporting

There is partial support for uploading build reports and build logs. This needs to be extended and should include anonymous build reports that the cabal-install client can generate (currently we only support the non-anonymous/detailed build reports). This way we can gather huge amounts of data on what packages work in what circumstances. We can use that to help inform maintainers and users and to edit package dependencies to match reality.

Generated tarfile exceeds OS limits

In particular, the number of subdirectories in core/packages can exceed (Linux) OS limits, making it impossible to unarchive the tarfile; that will fail with

tar: backup-2013-08-30/core/package/yesod-core-1.1.8.3: Cannot mkdir: Too many links

Better logging (in particular, support for warnings and errors)

For example, during backup, we issue a warning when we attempt to export a blob that doesn't exist on disk (39e050b); however, these warnings can easily get lost in the rest of the noise.

We should probably be using some sort of logging library, and be able to issue warnings and errors in such a way that log monitoring tools can pick them up and notify admins.

Avoid redirection

DELETE, PUT, and (in some cases) POST should not redirect, but rather return a document indicating the location of the new resource, if necessary, or other cues to continue browsing.

Continuous mode

At the moment, all we have is the utterly trivial rundocs.sh script; this should be more in line with the continuous mode of the mirror client (with support for --keep-going too, probably).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.