Re: Arch Linux minimal container userland 100% reproducible - now what?

2024-03-21 Thread Jelle van der Waa

Hey!

On 20/03/2024 13:42, kpcyrd wrote:

  INFO  arch_repro_status > All packages are reproducible!
  INFO  arch_repro_status > Your system is 100.00% reproducible.


\o/

Where do we go from here? It would be cool if the OCI container image 
itself could also be reproduced (bit-for-bit), but I'm not sure if 
there's any prior work (specifically for images listed as 'official' on 
Docker Hub)?


What would interest me a lot is if we gate the creation of the image on 
this, but of course that will not be a very trivial process.


Basically, we only publish an image if it is reproducible.


Input much appreciated!


Don't know much about reproducing OCI images, but another interesting 
goal would be reproducing the other images we produce:


https://mirror.pkgbuild.com/images/latest/

Likely needs a way to store the embedded packages.

Greetings,

Jelle



Re: Revising Go packaging guidelines (2024)

2024-03-21 Thread Morten Linderud
On Tue, Mar 19, 2024 at 12:17:11AM +0100, kpcyrd wrote:
> hello,

Yo,

Thanks for writing this.

> ## Suggestion
> 
> I'd like to propose changing this to something like:
> 
> > prepare() {
> >   cd ${pkgname}-${pkgver}
> >   go mod download
> > }
> >
> > build() {
> >   cd ${pkgname}-${pkgver}
> >   go build .
> > }
> >
> > package() {
> >   cd ${pkgname}-${pkgver}
> >   install -Dm0755 -t "${pkgdir}/usr/bin/" "${pkgname}"
> > }
> 
> Plus any extra flags (for example for debug packages to work, if any are
> needed at all - there's a note about this towards the end of this essay).
> Instead of suggesting two (three) different approaches, the packaging
> guidelines should endorse argv over environment variables (how to set them
> with environment variables can still be documented in a later section of the
> guideline).

While it would be cool if `go build` would do what you expect, it doesn't. Go
does not have some similar to `build.rs` that describes the targets so you need
to figure out where the binaries resides before you can build anything.

You could *try* to do `go build ./...` but you might end up with binaries you
don't want to build.

In more complicated examples you would need to use the `Makefile` as you do in
other projects because they are doing to much in their build system for the raw
`go build` calls to work.

tl;dr: It needs to be more complicated because upstream still pretends that `go
build` is a buildsystem.

> ## Passing flags over argv
> 
> Setting these options through environment variables is for cases when `go`
> isn't executed directly by our PKGBUILD, but instead by some indirection
> like a Makefile. Makefiles are more popular in Go projects than they are in
> e.g. Rust projects, but presumably because for many years (10+) there was no
> analogous to `env!("CARGO_PKG_VERSION")` to embed a version string into the
> binary for --version output.
> 
> Since almost exactly two years ago, in Go 1.18 released March 2022, there's
> now `runtime/debug.ReadBuildInfo` which gives you a reference to an embedded
> struct that contains a version string[1].
> 
> [1]: https://pkg.go.dev/runtime/debug#ReadBuildInfo
> 
> Hopefully more Go projects are going to favor this in the future over custom
> build scripts and passing `-X main.Version=...` with output from `git
> describe --tags`. If this catches on, people might think of `go build` more
> like they currently think of `cargo build` and I think the Go package
> guideline should encourage this.

This assumes we are pulling from git, *and* don't use `-buildvcs=false`. However
I don't see this likely for all projects and Makefiles do a lot more then *just*
being a wrapper for `-X` flags.

So while nice in theory, I don't think it would be workable in practise and
people would end up reverse engineering Makefiles if they want to drop it. It's
fine to use it if it exists.


> ## Using the Go native Linker
> 
> Binaries built by the Go compiler have been reproducible for a long time,
> however Go binaries built by Arch Linux usually aren't. This has led to some
> confusion, with bug reports to upstreams of Go software because it wasn't
> obvious that the package not being reproducible in this case isn't a problem
> in upstream's source code, but the way Arch Linux compiles it.
> 
> Arch Linux generally prefers binaries with hardening flags enabled[3] and
> therefore explicitly opts into a non-default linker (Cgo), but it seems to
> be the unpopular choice. Cgo seems to have less support than normal Go on
> Linux (evidently, since Cgo has been known to have reproducible build issues
> for years now). Other Linux distributions seem to stick to normal Go too,
> Nix has Cgo off by default[4] and searching through nixpkgs for
> "buildGoModule" yields about 2k results, searching for "CGO_ENABLED" has 105
> results, with more than half being "CGO_ENABLED=0" though. Alpine Linux only
> sets GOFLAGS globally[5] (which Arch Linux currently doesn't), searching for
> `rg -l --multiline '\tgo.*build'` in aports matches 356 files, `rg -l
> CGO_ENABLED=0` matches 23 files and `rg -l CGO_ENABLED=1` matches 18 files.

Generally I agree that we should remove `CGO_ENABLED` and rather set it for
unsupported plattform. It will however break existing porting efforts but it
should be solved somewhere else regardless.

ie riscv/arm/$someport set this in their buildflags.

> The global GOFLAGS as specified in Alpine Linux are:
> 
> > export GOFLAGS="-buildmode=pie -modcacherw -trimpath -buildvcs=false"
> 
> Which we could consider setting globally too, like we do with RUSTFLAGS.

The issue here is because `GOFLAGS` was standardized late in the development a
lot of the `Makefiles` people write for Go overwrites the entire variable and is
re-purposed to carry CLI flags which isn't compatible.

So while I think we should distribute proper Goflags here it's not going to
solve it for all cases as people still would need to deal with bad build
systems.

However we still need a

Re: Arch Linux minimal container userland 100% reproducible - now what?

2024-03-21 Thread Kristian Klausen

On 20.03.2024 13.42, kpcyrd wrote:
Where do we go from here? It would be cool if the OCI container image 
itself could also be reproduced (bit-for-bit), but I'm not sure if 
there's any prior work (specifically for images listed as 'official' 
on Docker Hub)?


Specifically what I mean - given a line like this:

FROM 
archlinux@sha256:2dbd72d1e5510e047db7f441bf9069e9c53391b87e04e5bee3f379cd03cec060


I want to reproduce the artifact(s) that are pulled in by this, with 
the packages our Arch Linux rebuilders have reproduced from source 
code. From what I understand this hash points to a json manifest that 
is not contained in the container image itself and was generated by 
the registry (should we archive them?), and this manifest then points 
to the sha256 of the tar containing the filesystem (I'm possibly 
missing an indirection here).


Hopefully one of the many SBOM formats can help with this. :P

I know the container image is built from these two repositories but I 
don't have any in-depth knowledge:


- 
https://github.com/docker-library/official-images/blob/master/library/archlinux

- https://gitlab.archlinux.org/archlinux/archlinux-docker


We do not control the full build pipeline for the Docker Hub official 
Arch Linux image.


The workflow is basically (links for the 20240101.0.204074 tag provided):
1. Every week[1] new tarballs[2] and Dockerfiles[3] are built
2. A PR[4] is opened for the official-images repo on GitHub
3. The PR is merged
4. The Dockerfiles are built by official-images's build 
infrastructure[5] and pushed to Docker Hub


I'm not sure to what extent the official-images's build infrastructure 
supports "reproducible builds", but it was discussed[6] and implemented 
in some capacity for the golang image[7] in January. There is also a 
existing issue for reproducibility in archlinux-docker[8].


For our images published at docker.io/archlinux/archlinux, Quay.io and 
ghcr.io, we do control the whole build pipeline and we can more easily 
tweak the pipeline to support "reproducible builds" if desired. They are 
also already signed with cosign FWIW.


[1] 
https://gitlab.archlinux.org/archlinux/archlinux-docker/-/pipelines/87673

[2] https://gitlab.archlinux.org/archlinux/archlinux-docker/-/packages/1277
[3] 
https://gitlab.archlinux.org/archlinux/archlinux-docker/-/tree/v20240101.0.204074

[4] https://github.com/docker-library/official-images/pull/15984
[5] https://doi-janky.infosiftr.net/
[6] https://github.com/docker-library/official-images/issues/16044
[7] https://github.com/docker-library/golang/pull/505
[8] https://gitlab.archlinux.org/archlinux/archlinux-docker/-/issues/44

Cheers,
Kristian


OpenPGP_signature.asc
Description: OpenPGP digital signature