[
  {
    "path": ".gitignore",
    "content": "/target\n/src.tgz\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"asdf\"\nversion = \"0.1.1\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM docker.io/rust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64\nWORKDIR /app\nCOPY . .\nRUN cargo build --release --locked --target=x86_64-unknown-linux-musl\n\nFROM docker.io/alpine@sha256:eb3e4e175ba6d212ba1d6e04fc0782916c08e1c9d7b45892e9796141b1d379ae\nCOPY --from=0 /app/target/x86_64-unknown-linux-musl/release/asdf /asdf\nENTRYPOINT [\"/asdf\"]\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     https://www.apache.org/licenses/LICENSE-2.0\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\n   To apply the Apache License to your work, attach the following\n   boilerplate notice, with the fields enclosed by brackets \"[]\"\n   replaced with your own identifying information. (Don't include\n   the brackets!)  The text should be enclosed in the appropriate\n   comment syntax for the file format. We also recommend that a\n   file or class name and description of purpose be included on the\n   same \"printed page\" as the copyright notice for easier\n   identification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n\thttps://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Permission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "build:\n\tdocker run --rm -v \"$(PWD):/app\" -w /app -u \"$(shell id -u):$(shell id -g)\" \\\n\t\trust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64 \\\n\t\tcargo build --release --locked --target=x86_64-unknown-linux-musl\n\ndocker:\n\tsudo buildah bud --timestamp 0 --tag asdf\n\nsrc.tgz:\n\tgit archive -o src.tgz HEAD\n\n.PHONY: build docker src.tgz\n"
  },
  {
    "path": "PKGBUILD",
    "content": "pkgname=i-probably-didnt-backdoor-this\npkgver=0.1.1\npkgrel=1\narch=('x86_64')\nmakedepends=('cargo')\nsource=(src.tgz)\nsha256sums=(SKIP)\n\nbuild() {\n    cargo build --release --locked\n}\n\npackage() {\n    install -Dm 755 target/release/asdf -t \"${pkgdir}/usr/bin/\"\n}\n"
  },
  {
    "path": "README.md",
    "content": "# I probably didn't backdoor this\n\nThis is a practical attempt at shipping a program and having reasonably solid\nevidence there's probably no backdoor. All source code is annotated and there\nare instructions explaining how to use reproducible builds to rebuild the\nartifacts distributed in this repository from source.\n\nThe idea is shifting the burden of proof from \"you need to prove there's a\nbackdoor\" to \"we need to prove there's probably no backdoor\". This repository\nis less about code (we're going to try to keep code at a minimum actually) and\ninstead contains technical writing that explains why these controls are\neffective and how to verify them. You are very welcome to adopt the techniques\nused here in your projects.\n\nThe author should be assumed to be your average software developer, who might\nbe suspiciously good with computer security, but doesn't have nation-state\ncapabilities.\n\n## Contents\n\n- [Preparing retroactive reviews](#preparing-retroactive-reviews)\n- [Pinned external resources](#pinned-external-resources)\n- [Reading the source code](#reading-the-source-code)\n- [Reproducing the ELF binary](#reproducing-the-elf-binary)\n- [Reproducing the Docker image](#reproducing-the-docker-image)\n- [Reproducing the Arch Linux package](#reproducing-the-arch-linux-package)\n- [Notes on security patches](#notes-on-security-patches)\n- [How is this related to Reproducible Builds](#how-is-this-related-to-reproducible-builds)\n- [Similar work](#similar-work)\n\n### Preparing retroactive reviews\n\nSince \"reading the source code\" requires advanced domain knowledge, this\nsection describes a pen-and-paper aproach that can be used to cryptographically\nensure you can retro-actively review what you executed, even if you didn't\nreview before you executed it. Pen-and-paper should be taken literally here to\nensure this can't be modified by software. If done correctly, you don't need to\nread the other sections immediately, instead you're creating an immutable\npapertrail that can later be used by a subject matter expert. Note that the\nreview needs to happen on a different computer than the one that executed the\ncode, for safety reasons.\n\nBecause it's in the authors interest to prove there are no backdoors, all\nexternal resources that are not contained within this repository need to be\nreferred to in a way that's addressing its content (more on this in the next\nsection).\n\nWe're starting with the main repository by cloning it and showing the commit\nhash we're about to work with:\n\n```sh\n$ git clone https://github.com/kpcyrd/i-probably-didnt-backdoor-this\n$ cd i-probably-didnt-backdoor-this/\n$ git rev-parse HEAD\naabbccddeeff00112233445566778899aabbccdd\n```\n\nThe hash in the last line is going to be different for you. This 40 character\nid is what you need for your paper trail, you need to write this down\n(preferably along with the current date) and keep it in a safe location. It\nneeds to be protected from undetected tampering but isn't secret, so you may\ncreate copies or even post it publicly.\n\nThis id uniquely identifies all files in this repository with their content. If\na file is modified/removed/added/renamed in this repository, this hash changes\ntoo.\n\nIf you want to read more about the cryptographic properties behind this, look\ninto [Merkel trees](https://en.wikipedia.org/wiki/Merkle_tree).\n\n### Pinned external resources\n\nIn the previous section we've described how git is automatically tracking the\ncontent of all files in this repository with a single hash. Software projects\noften rely on external resources downloaded from the internet, like libraries.\n\nDownloading resources from the internet doesn't weaken what we've established\nin the previous section, as long as:\n\n1. The content of the resource is pinned with a cryptographic hash and the hash\n   is recorded in the git repository.\n2. We can be reasonably sure the resource is not going to disappear. If they\n   disappear you could attempt to use backup copies, as long as they match the\n   cryptographic hash in the repository.\n\nIf at least one of those two doesn't apply we \"broke the chain of custody\".\n\nWe don't have to implement this ourselves, but `cargo` and `docker` implement\nthis internally.\n\n### Reading the source code\n\nThe repository contains 6 source code files, there's a writeup for each of\nthem. Files ending with `.md` are documentation.\n\n- [`Cargo.toml`](writeups/cargo-toml.md) - Contains metadata about the project and a list of dependencies (if any)\n- [`Cargo.lock`](writeups/cargo-lock.md) - Automatically generated, records sha256 checksums for all dependencies\n- [`src/main.rs`](writeups/main-rs.md) - The actual source code of our program\n- [`Makefile`](writeups/makefile.md) - A wrapper script with build instructions\n- [`Dockerfile`](writeups/dockerfile.md) - Contains build instructions for a container image\n- [`PKGBUILD`](writeups/pkgbuild.md) - Contains build instructions for an Arch Linux package\n\n### Reproducing the ELF binary\n\nThe binary is built in a docker container, the exact command can be found in\nthe [`Makefile`](writeups/makefile.md). Running make executes the build in a\nspecific Docker image (the official rust 1.54.0 alpine 3.14 docker image).\n\nBecause the build environment is pinned and there's nothing introducing\nnon-determinism to the build (like recording the build time), running the build\non different computers (or even operating systems) should always result in the\nsame binary.\n\nStart the build with this command:\n\n```sh\n$ make\n```\n\nThis command should finish quite quickly and produces a binary that matches\nthis checksum:\n\n```sh\n$ b2sum target/x86_64-unknown-linux-musl/release/asdf\ncd112870cdf12052e5604e7559e45f95cac4e52a45e91c9d9285a22a82c6392e95fbf0dc5f784837e7769a3ce14c898c866a85e4d60b051d3416875e301e28aa  target/x86_64-unknown-linux-musl/release/asdf\n```\n\nDownloading and hashing the pre-compiled binary from the [releases\npage](https://github.com/kpcyrd/i-probably-didnt-backdoor-this/releases) should\ngive you an identical hash:\n\n```sh\n$ curl -LsS 'https://github.com/kpcyrd/i-probably-didnt-backdoor-this/releases/download/v0.1.1/asdf' | b2sum -\ncd112870cdf12052e5604e7559e45f95cac4e52a45e91c9d9285a22a82c6392e95fbf0dc5f784837e7769a3ce14c898c866a85e4d60b051d3416875e301e28aa  -\n```\n\nIf you get the same checksum you've successfully reproduced the binary. If\nthere's no difference between the pre-compiled binary and the one you built\nyourself this means the pre-compiled binary is just as trustworthy as the one\nyou built yourself.\n\n### Reproducing the Docker image\n\nThere's a Dockerfile in the repository that always produces the same\nbit-for-bit identical image. It's a multi-stage build, so it builds the binary\nin one temporary image and then creates the real image with just `FROM`, `COPY`\nand `ENTRYPOINT`. The build environment is virtually identical to what we're\nusing in the previous section, then we're copying it over into an Alpine image\nthat's pinned by its sha256 hash.\n\n```sh\n$ make docker\nsudo buildah bud --timestamp 0 --tag asdf\n[1/2] STEP 1/4: FROM docker.io/rust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64\n[1/2] STEP 2/4: WORKDIR /app\n[1/2] STEP 3/4: COPY . .\n[1/2] STEP 4/4: RUN cargo build --release --locked --target=x86_64-unknown-linux-musl\n    Finished release [optimized] target(s) in 0.02s\n[2/2] STEP 1/3: FROM docker.io/alpine@sha256:eb3e4e175ba6d212ba1d6e04fc0782916c08e1c9d7b45892e9796141b1d379ae\n[2/2] STEP 2/3: COPY --from=0 /app/target/x86_64-unknown-linux-musl/release/asdf /asdf\n[2/2] STEP 3/3: ENTRYPOINT [\"/asdf\"]\n[2/2] COMMIT asdf\nGetting image source signatures\nCopying blob bc276c40b172 skipped: already exists\nCopying blob 7d377d49a080 done\nCopying config f0b71b1591 done\nWriting manifest to image destination\nStoring signatures\n--> f0b71b1591c\nSuccessfully tagged localhost/asdf:latest\nf0b71b1591cf50cf3609494187083741c1021fd99f6168ab8283c4390954cef1\n```\n\nThe last line is the hash of the image we just built. We're using buildah to\nbuild the image because there's no way to set the layer timestamp with docker\n(causing the hash to vary). Unfortunately buildah records it's version, this\nimage has been built with `1.22.3`.\n\nThe pre-compiled images can be found on the [container\nregistry](https://github.com/kpcyrd/i-probably-didnt-backdoor-this/pkgs/container/i-probably-didnt-backdoor-this)\n(also linked in the side-bar on the right). Pull the image with this command:\n\n```sh\n$ docker pull ghcr.io/kpcyrd/i-probably-didnt-backdoor-this:latest\nlatest: Pulling from kpcyrd/i-probably-didnt-backdoor-this\n50341f5fa632: Already exists\n163594b80890: Pull complete\nDigest: sha256:11cc7ec2b907a325fa3565039d990a466a7d83a06aa7dffdebba38d495d1571d\nStatus: Downloaded newer image for ghcr.io/kpcyrd/i-probably-didnt-backdoor-this:latest\nghcr.io/kpcyrd/i-probably-didnt-backdoor-this:latest\n```\n\nYou'll noticed the hash doesn't seem to match at first, but if everything\nworked the image id is indeed the same:\n\n```sh\n$ docker images --no-trunc ghcr.io/kpcyrd/i-probably-didnt-backdoor-this\nREPOSITORY                                      TAG       IMAGE ID                                                                  CREATED        SIZE\nghcr.io/kpcyrd/i-probably-didnt-backdoor-this   latest    sha256:f0b71b1591cf50cf3609494187083741c1021fd99f6168ab8283c4390954cef1   51 years ago   9.38MB\n```\n\n### Reproducing the Arch Linux package\n\nThere's a custom Arch Linux repository that's distributing a pre-built package:\n\n```\n[i-probably-didnt-backdoor-this]\nServer = https://pkgbuild.com/~kpcyrd/$repo/os/$arch/\n```\n\nThis package can be reproduced from source, the full writeup for this can be\nfound in [this document](writeups/archlinux.md).\n\n### Notes on security patches\n\nWe've pinned very specific versions in multiple places (including the\ncompiler). This is often considered bad style since we're now in charge of\nkeeping all of this updated.\n\nIf you're adopting this in your own project you should periodically release new\nversions, even if you aren't making any changes to the code anymore. This also\napplies to many modern programming ecosystems these days due to lock files.\n\nThe following places need to be updated occasionally, causing the artifact\nhashes to change.\n\n- Dependencies in Cargo.toml/Cargo.lock (if any, cargo update)\n- `FROM` lines in Dockerfile (docker pull rust:alpine, docker pull alpine:latest)\n- The build image in the Makefile (docker pull rust:alpine)\n\n### How is this related to Reproducible Builds\n\nThere's quite a bit of overlap with the [reproducible\nbuilds](https://reproducible-builds.org) project. The techniques used to\nrebuild the binary artifacts are only possible because the builds for this\nproject are [reproducible](https://reproducible-builds.org/docs/definition/).\n\nThis project also attempts to exclusively use binaries distributed by\nhigh-profile targets like Alpine Linux and the Rust project. This is commonly\naccepted as \"reasonable\" in the wider tech industry, but makes their build\nservers and signing keys extremely valuable.\n\nThe reproducible builds effort attempts to reduce this risk by allowing\nindependent parties to \"reproduce\" their packages with \"confirmation rebuilds\",\njust like you did when following the instructions here!\n\n### Similar work\n\n- [Verifying a Tails image for reproducibility](https://tails.boum.org/contribute/build/reproducible/)\n- [Reproducing Monero Binaries](https://github.com/monero-project/monero/blob/master/contrib/gitian/README.md)\n- [i-probably-didnt-backdoor-this](https://github.com/bureado/i-probably-didnt-backdoor-this)\n  fork by @bureado using unprivileged build containers with podman\n- [A similar guide using NixOS and\n  Bazel](https://github.com/mlieberman85/reproducible-examples) by\n  @mlieberman85\n\n## Acknowledgments\n\nThis project was funded by Google, The Linux Foundation, and people like you\nand me through [GitHub sponsors](https://github.com/sponsors/kpcyrd).\n\n♥️♥️♥️\n\n## License\n\nLicensed under either of Apache License, Version 2.0 or MIT license at your\noption.\n"
  },
  {
    "path": "src/main.rs",
    "content": "fn main() {\n    println!(\"Hello, world!\");\n}\n"
  },
  {
    "path": "writeups/archlinux.md",
    "content": "### Reproducing the Arch Linux package\n\nThere's a custom Arch Linux repository that's distributing this package.\n\n    [i-probably-didnt-backdoor-this]\n    Server = https://pkgbuild.com/~kpcyrd/$repo/os/$arch/\n\nThis repository contains these 6 files:\n\n- [i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst)\n  This is the pre-built package that's going to be installed on the system.\n  This is the file we want to reproduce.\n- [i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst.sig](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst.sig)\n  This is a signature that we can use to verify the previous file was signed by\n  somebody with control over a specific private key. This signature is also\n  included in the .db file, so this file might not get downloaded.\n- [i-probably-didnt-backdoor-this.db](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this.db)\n  This contains an index of all packages in the repository. pacman downloads\n  this to learn about the packages in this repository.\n- [i-probably-didnt-backdoor-this.db.tar.gz](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this.db.tar.gz)\n  identical with the .db file for compatibility reasons.\n- [i-probably-didnt-backdoor-this.files](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this.files)\n  This contains an index of all the files in each package, this is only used by\n  `pacman -F` operations.\n- [i-probably-didnt-backdoor-this.files.tar.gz](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this.files.tar.gz)\n  identical with the .files file for compatibility reasons.\n\nThis repository has been setup from this git repository using the following\ncommands. You don't need to run them, they're only included for documentation\npurpose.\n\n- `extra-x86_64-build` to build the package from the [`PKGBUILD`](pkgbuild.md)\n  instructions\n- `gpg --detach-sign --no-armor -u kpcyrd@archlinux.org\n  i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst` signs the package\n  with my key\n- `repo-add i-probably-didnt-backdoor-this.db.tar.gz\n  i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst`  this creates a\n  package database with our package\n\n`extra-x86_64-build` uses a clean chroot and records the environment in a file\ncalled `.BUILDINFO` that's embedded in the package. We download the package and\nlist what's inside of it:\n\n    $ wget https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst\n    [...]\n    $ b2sum i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst\n    84f398fae04a0d73647a7074dd9669e7899d8b702c30c928606ec2b0fde739b8131f817e77631ed0ffef4696380fa5478a0ebe0aa4e0b3d33ea7e3ee2910678c  i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst\n    $ tar tf i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst\n    .BUILDINFO\n    .MTREE\n    .PKGINFO\n    usr/\n    usr/bin/\n    usr/bin/asdf\n\nThere's the .BUILDINFO file we already mentioned before, 2 files that are used\ninternally by pacman, and the binary that is distributed in this package.\n\nWe only really care about the `.BUILDINFO` file, let's look into it:\n\n    $ tar xfO i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst .BUILDINFO\n    format = 2\n    pkgname = i-probably-didnt-backdoor-this\n    pkgbase = i-probably-didnt-backdoor-this\n    pkgver = 0.1.1-1\n    pkgarch = x86_64\n    pkgbuild_sha256sum = b6e4c48bf0c3ee73ef80e6f29e646f191b204695b725684664a64c12cb7ee150\n    packager = kpcyrd <kpcyrd@archlinux.org>\n    builddate = 1630668222\n    builddir = /build\n    startdir = /startdir\n    buildtool = makepkg\n    buildtoolver = 6.0.0\n    buildenv = !distcc\n    buildenv = color\n    buildenv = !ccache\n    buildenv = check\n    buildenv = !sign\n    options = strip\n    options = docs\n    options = !libtool\n    options = !staticlibs\n    options = emptydirs\n    options = zipman\n    options = purge\n    options = !debug\n    installed = acl-2.3.1-1-x86_64\n    installed = archlinux-keyring-20210820-1-any\n    installed = attr-2.5.1-1-x86_64\n    installed = audit-3.0.4-1-x86_64\n    installed = autoconf-2.71-1-any\n    installed = automake-1.16.4-1-any\n    installed = bash-5.1.008-1-x86_64\n    installed = binutils-2.36.1-3-x86_64\n    installed = bison-3.7.6-1-x86_64\n    installed = bzip2-1.0.8-4-x86_64\n    installed = ca-certificates-20210603-1-any\n    installed = ca-certificates-mozilla-3.69.1-1-x86_64\n    installed = ca-certificates-utils-20210603-1-any\n    installed = coreutils-8.32-1-x86_64\n    installed = curl-7.78.0-1-x86_64\n    installed = db-5.3.28-5-x86_64\n    installed = diffutils-3.8-1-x86_64\n    installed = e2fsprogs-1.46.4-1-x86_64\n    installed = elfutils-0.185-1-x86_64\n    installed = expat-2.4.1-1-x86_64\n    installed = fakeroot-1.25.3-2-x86_64\n    installed = file-5.40-5-x86_64\n    installed = filesystem-2021.05.31-1-x86_64\n    installed = findutils-4.8.0-1-x86_64\n    installed = flex-2.6.4-3-x86_64\n    installed = gawk-5.1.0-1-x86_64\n    installed = gc-8.0.4-4-x86_64\n    installed = gcc-11.1.0-1-x86_64\n    installed = gcc-libs-11.1.0-1-x86_64\n    installed = gdbm-1.20-1-x86_64\n    installed = gettext-0.21-1-x86_64\n    installed = glib2-2.68.4-1-x86_64\n    installed = glibc-2.33-5-x86_64\n    installed = gmp-6.2.1-1-x86_64\n    installed = gnupg-2.2.29-1-x86_64\n    installed = gnutls-3.7.2-2-x86_64\n    installed = gpgme-1.16.0-1-x86_64\n    installed = grep-3.6-1-x86_64\n    installed = groff-1.22.4-6-x86_64\n    installed = guile-2.2.7-1-x86_64\n    installed = gzip-1.10-3-x86_64\n    installed = iana-etc-20210728-1-any\n    installed = icu-69.1-1-x86_64\n    installed = keyutils-1.6.3-1-x86_64\n    installed = krb5-1.19.1-1-x86_64\n    installed = less-1:590-1-x86_64\n    installed = libarchive-3.5.2-1-x86_64\n    installed = libassuan-2.5.5-1-x86_64\n    installed = libcap-2.53-1-x86_64\n    installed = libcap-ng-0.8.2-3-x86_64\n    installed = libcroco-0.6.13-2-x86_64\n    installed = libedit-20210522_3.1-1-x86_64\n    installed = libelf-0.185-1-x86_64\n    installed = libffi-3.3-4-x86_64\n    installed = libgcrypt-1.9.4-1-x86_64\n    installed = libgpg-error-1.42-1-x86_64\n    installed = libidn2-2.3.2-1-x86_64\n    installed = libksba-1.6.0-1-x86_64\n    installed = libldap-2.4.59-2-x86_64\n    installed = libmpc-1.2.1-1-x86_64\n    installed = libnghttp2-1.44.0-1-x86_64\n    installed = libp11-kit-0.24.0-1-x86_64\n    installed = libpsl-0.21.1-1-x86_64\n    installed = libsasl-2.1.27-3-x86_64\n    installed = libseccomp-2.5.1-2-x86_64\n    installed = libsecret-0.20.4-1-x86_64\n    installed = libssh2-1.9.0-3-x86_64\n    installed = libtasn1-4.17.0-1-x86_64\n    installed = libtirpc-1.3.2-1-x86_64\n    installed = libtool-2.4.6+42+gb88cebd5-16-x86_64\n    installed = libunistring-0.9.10-3-x86_64\n    installed = libxcrypt-4.4.25-1-x86_64\n    installed = libxml2-2.9.10-9-x86_64\n    installed = linux-api-headers-5.12.3-1-any\n    installed = llvm-libs-12.0.1-3-x86_64\n    installed = lz4-1:1.9.3-2-x86_64\n    installed = m4-1.4.19-1-x86_64\n    installed = make-4.3-3-x86_64\n    installed = mpfr-4.1.0.p13-1-x86_64\n    installed = ncurses-6.2-2-x86_64\n    installed = nettle-3.7.3-1-x86_64\n    installed = npth-1.6-3-x86_64\n    installed = openssl-1.1.1.l-1-x86_64\n    installed = p11-kit-0.24.0-1-x86_64\n    installed = pacman-6.0.0-5-x86_64\n    installed = pacman-mirrorlist-20210822-1-any\n    installed = pam-1.5.1-1-x86_64\n    installed = pambase-20210605-2-any\n    installed = patch-2.7.6-8-x86_64\n    installed = pcre-8.45-1-x86_64\n    installed = pcre2-10.37-1-x86_64\n    installed = perl-5.34.0-2-x86_64\n    installed = pinentry-1.1.1-1-x86_64\n    installed = pkgconf-1.7.3-1-x86_64\n    installed = readline-8.1.001-1-x86_64\n    installed = rust-1:1.54.0-1-x86_64\n    installed = sed-4.8-1-x86_64\n    installed = shadow-4.8.1-4-x86_64\n    installed = sqlite-3.36.0-1-x86_64\n    installed = sudo-1.9.7.p2-1-x86_64\n    installed = systemd-libs-249.4-1-x86_64\n    installed = tar-1.34-1-x86_64\n    installed = texinfo-6.8-2-x86_64\n    installed = tzdata-2021a-2-x86_64\n    installed = util-linux-2.37.2-1-x86_64\n    installed = util-linux-libs-2.37.2-1-x86_64\n    installed = which-2.21-5-x86_64\n    installed = xz-5.2.5-1-x86_64\n    installed = zlib-1:1.2.11-4-x86_64\n    installed = zstd-1.5.0-1-x86_64\n\nThis seems like a lot of control from a file we just downloaded from the\ninternet, but note that most of these are only informal and the tooling we're\ngoing to use only allows packages to be installed that have been officially\npublished in Arch Linux. The packages listed here are basically a base-devel\ninstall plus `makedepends=`.\n\nFor official Arch Linux packages the field `pkgbase` is used with\n[`asp`](https://man.archlinux.org/man/extra/asp/asp.1.en) to fetch the build\ninstructions and `pkgbuild_sha256sum` is used to identify the right commit. For\ntechnical reasons the commit id is not yet available when the Arch Linux\npackage is built.\n\nBecause in our case everything is contained within this repository and we\nalready know the right commit, so we can skip this step. The Arch Linux tooling\nexpects a tar ball, so we're generating one from this repository. The commands\nthat are used for this can be found in the [`Makefile`](makefile.md).\n\n    $ make src.tgz\n\nUsing the Arch Linux reproducible builds tooling we're taking the build\nenvironment from the package, the [`PKGBUILD`](pkgbuild.md) build instructions\nfrom this repository, and the `src.tgz` tar ball we've just generated and\nattempt to create an identical package.\n\n`makerepropkg` can be installed with `pacman -S devtools`.\n\n    $ makerepropkg i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst\n    Create subvolume '/var/lib/archbuild/reproducible/root'\n    ==> Creating install root at /var/lib/archbuild/reproducible/root\n    ==> Installing packages to /var/lib/archbuild/reproducible/root\n    warning: database file for 'core' does not exist (use '-Sy' to download)\n    warning: database file for 'extra' does not exist (use '-Sy' to download)\n    warning: database file for 'community' does not exist (use '-Sy' to download)\n    loading packages...\n    resolving dependencies...\n    looking for conflicting packages...\n\n    Packages (110) acl-2.3.1-1  archlinux-keyring-20210820-1  attr-2.5.1-1  audit-3.0.4-1  autoconf-2.71-1\n                   automake-1.16.4-1  bash-5.1.008-1  binutils-2.36.1-3  bison-3.7.6-1  bzip2-1.0.8-4\n                   ca-certificates-20210603-1  ca-certificates-mozilla-3.69.1-1  ca-certificates-utils-20210603-1\n                   coreutils-8.32-1  curl-7.78.0-1  db-5.3.28-5  diffutils-3.8-1  e2fsprogs-1.46.4-1  elfutils-0.185-1\n                   expat-2.4.1-1  fakeroot-1.25.3-2  file-5.40-5  filesystem-2021.05.31-1  findutils-4.8.0-1\n                   flex-2.6.4-3  gawk-5.1.0-1  gc-8.0.4-4  gcc-11.1.0-1  gcc-libs-11.1.0-1  gdbm-1.20-1  gettext-0.21-1\n                   glib2-2.68.4-1  glibc-2.33-5  gmp-6.2.1-1  gnupg-2.2.29-1  gnutls-3.7.2-2  gpgme-1.16.0-1  grep-3.6-1\n                   groff-1.22.4-6  guile-2.2.7-1  gzip-1.10-3  iana-etc-20210728-1  icu-69.1-1  keyutils-1.6.3-1\n                   krb5-1.19.1-1  less-1:590-1  libarchive-3.5.2-1  libassuan-2.5.5-1  libcap-2.53-1  libcap-ng-0.8.2-3\n                   libcroco-0.6.13-2  libedit-20210522_3.1-1  libelf-0.185-1  libffi-3.3-4  libgcrypt-1.9.4-1\n                   libgpg-error-1.42-1  libidn2-2.3.2-1  libksba-1.6.0-1  libldap-2.4.59-2  libmpc-1.2.1-1\n                   libnghttp2-1.44.0-1  libp11-kit-0.24.0-1  libpsl-0.21.1-1  libsasl-2.1.27-3  libseccomp-2.5.1-2\n                   libsecret-0.20.4-1  libssh2-1.9.0-3  libtasn1-4.17.0-1  libtirpc-1.3.2-1\n                   libtool-2.4.6+42+gb88cebd5-16  libunistring-0.9.10-3  libxcrypt-4.4.25-1  libxml2-2.9.10-9\n                   linux-api-headers-5.12.3-1  llvm-libs-12.0.1-3  lz4-1:1.9.3-2  m4-1.4.19-1  make-4.3-3\n                   mpfr-4.1.0.p13-1  ncurses-6.2-2  nettle-3.7.3-1  npth-1.6-3  openssl-1.1.1.l-1  p11-kit-0.24.0-1\n                   pacman-6.0.0-5  pacman-mirrorlist-20210822-1  pam-1.5.1-1  pambase-20210605-2  patch-2.7.6-8\n                   pcre-8.45-1  pcre2-10.37-1  perl-5.34.0-2  pinentry-1.1.1-1  pkgconf-1.7.3-1  readline-8.1.001-1\n                   rust-1:1.54.0-1  sed-4.8-1  shadow-4.8.1-4  sqlite-3.36.0-1  sudo-1.9.7.p2-1  systemd-libs-249.4-1\n                   tar-1.34-1  texinfo-6.8-2  tzdata-2021a-2  util-linux-2.37.2-1  util-linux-libs-2.37.2-1\n                   which-2.21-5  xz-5.2.5-1  zlib-1:1.2.11-4  zstd-1.5.0-1\n\n    Total Installed Size:  1330.71 MiB\n\n    :: Proceed with installation? [Y/n]\n    (110/110) checking keys in keyring                                     [#######################################] 100%\n    (110/110) checking package integrity                                   [#######################################] 100%\n    (110/110) loading package files                                        [#######################################] 100%\n    (110/110) checking for file conflicts                                  [#######################################] 100%\n    (110/110) checking available disk space                                [#######################################] 100%\n    :: Processing package changes...\n    (  1/110) installing linux-api-headers                                 [#######################################] 100%\n    (  2/110) installing tzdata                                            [#######################################] 100%\n    (  3/110) installing iana-etc                                          [#######################################] 100%\n    (  4/110) installing filesystem                                        [#######################################] 100%\n\nThis takes some time but should eventually print the following text at the end:\n\n    ==> Extracting sources...\n      -> Extracting src.tgz with bsdtar\n    ==> Starting build()...\n       Compiling asdf v0.1.1 (/build/i-probably-didnt-backdoor-this/src)\n        Finished release [optimized] target(s) in 1.63s\n    ==> Entering fakeroot environment...\n    ==> Starting package()...\n    ==> Tidying install...\n      -> Removing libtool files...\n      -> Purging unwanted files...\n      -> Removing static library files...\n      -> Stripping unneeded symbols from binaries and libraries...\n      -> Compressing man and info pages...\n    ==> Checking for packaging issues...\n    ==> Creating package \"i-probably-didnt-backdoor-this\"...\n      -> Generating .PKGINFO file...\n      -> Generating .BUILDINFO file...\n    warning: database file for 'core' does not exist (use '-Sy' to download)\n    warning: database file for 'extra' does not exist (use '-Sy' to download)\n    warning: database file for 'community' does not exist (use '-Sy' to download)\n      -> Generating .MTREE file...\n      -> Compressing package...\n    ==> Leaving fakeroot environment.\n    ==> Finished making: i-probably-didnt-backdoor-this 0.1.1-1 (Fri 03 Sep 2021 01:26:15 PM CEST)\n      -> built succeeded! built packages can be found in /var/lib/archbuild/reproducible/testenv/pkgdest\n    ==> comparing artifacts...\n      -> Package 'i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst' successfully reproduced!\n\nThis means we've successfully built a package from source that is bit-for-bit\nidentical, including every file inside of it. The first is the package we\ndownloaded, the second is the package we built from source.\n\n```sh\n$ b2sum i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst /var/lib/archbuild/reproducible/testenv/pkgdest/i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst\n84f398fae04a0d73647a7074dd9669e7899d8b702c30c928606ec2b0fde739b8131f817e77631ed0ffef4696380fa5478a0ebe0aa4e0b3d33ea7e3ee2910678c  i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst\n84f398fae04a0d73647a7074dd9669e7899d8b702c30c928606ec2b0fde739b8131f817e77631ed0ffef4696380fa5478a0ebe0aa4e0b3d33ea7e3ee2910678c  /var/lib/archbuild/reproducible/testenv/pkgdest/i-probably-didnt-backdoor-this-0.1.1-1-x86_64.pkg.tar.zst\n```\n"
  },
  {
    "path": "writeups/cargo-lock.md",
    "content": "# `Cargo.lock`\n\nThis file is automatically generated, it usually contains checksums of the\ndependencies of the project, but since our project doesn't have any it only\nshows our name and version that we've seen in [`Cargo.toml`](cargo-toml.md).\n\n```toml\n# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\nversion = 3\n\n[[package]]\nname = \"asdf\"\nversion = \"0.1.1\"\n```\n"
  },
  {
    "path": "writeups/cargo-toml.md",
    "content": "# `Cargo.toml`\n\nThis is mostly defaults from running `cargo new --bin asdf`:\n\n```toml\n[package]\nname = \"asdf\"\nversion = \"0.1.1\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\n```\n\n- `name = \"asdf\"` is the name of our project. This isn't really used for\n  anything but the binary name.\n- `version = \"0.1.1\"` is the version of our project.\n- `edition = \"2018\"` this means we're opting into new features of the Rust\n  compiler. If unspecified rustc is using the 2015 edition, the 2018 edition is\n  the default for new projects.\n\nThe `[dependencies]` section is able to reference other code that isn't part of\nthis repository, but there are none in this case because there are no lines\nafter this one.\n"
  },
  {
    "path": "writeups/dockerfile.md",
    "content": "# `Dockerfile`\n\n```dockerfile\nFROM docker.io/rust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64\nWORKDIR /app\nCOPY . .\nRUN cargo build --release --locked --target=x86_64-unknown-linux-musl\n\nFROM docker.io/alpine@sha256:eb3e4e175ba6d212ba1d6e04fc0782916c08e1c9d7b45892e9796141b1d379ae\nCOPY --from=0 /app/target/x86_64-unknown-linux-musl/release/asdf /asdf\nENTRYPOINT [\"/asdf\"]\n```\n\nThe Dockerfile has two stages, the first one compiles the source code:\n\n- `FROM\n  docker.io/rust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64`\n  This describes the image we use to build the binary for our Docker image.\n  This is the same image we also referenced in the Makefile.\n- `WORKDIR /app` By default the working directory is `/`, this line creates a\n  folder that we're going to compile in and change the working directory to\n  this folder.\n- `COPY . .` This copies the content of the current directory of the build\n  system into the container. The current dirctory on the build system is\n  expected to be the folder that this repository was cloned to, so the files\n  that are copied are only those from the git repository.\n- `RUN cargo build --release --locked --target=x86_64-unknown-linux-musl` This\n  compiles the rust source code into a binary. The command is explained in\n  detail in the [`Makefile`](makefile.md) writeup. This commnand is likely making our temporary\n\nThe temporary build image is done at this point, the second `FROM` starts a new\nimage:\n\n- `FROM\n  docker.io/alpine@sha256:eb3e4e175ba6d212ba1d6e04fc0782916c08e1c9d7b45892e9796141b1d379ae`\n  This is the base image for our final image that we're going to upload. The\n  rust compiler is not required anymore so we're using one of the official\n  [alpine](https://hub.docker.com/_/alpine) images here.\n- `COPY --from=0 /app/target/x86_64-unknown-linux-musl/release/asdf /asdf` This\n  copies the build artifact from the previous image into the final Docker\n  image. If this binary is reproducible the final Docker image is going to be\n  reproducible too.\n- `ENTRYPOINT [\"/asdf\"]` This sets the `/asdf` binary we just copied into the\n  container as the entrypoint, meaning if the container is executed, this\n  binary runs, nothing else.\n"
  },
  {
    "path": "writeups/main-rs.md",
    "content": "# `src/main.rs`\n\nThis is our program. We're creating a function called `main` that contains a\ncall to the `println!` macro to print the string `Hello, world!` to stdout.\n\n```rust\nfn main() {\n    println!(\"Hello, world!\");\n}\n```\n"
  },
  {
    "path": "writeups/makefile.md",
    "content": "# `Makefile`\n\nThis is likely the most complicated file in this repository, we're going to\nexplain this in depth.\n\n```make\nbuild:\n\tdocker run --rm -v \"$(PWD):/app\" -w /app -u \"$(shell id -u):$(shell id -g)\" \\\n\t\trust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64 \\\n\t\tcargo build --release --locked --target=x86_64-unknown-linux-musl\n\ndocker:\n\tsudo buildah bud --timestamp 0 --tag asdf\n\nsrc.tgz:\n\tgit archive -o src.tgz HEAD\n\n.PHONY: build docker src.tgz\n```\n\n## `build:`\n\nThis builds the ELF binary.\n\n- `docker run` This means we're going to run a [docker\n  container](https://www.docker.com/resources/what-container)\n- `--rm` This means the container should be temporary and is going to be\n  deleted after our command completes.\n- `-v \"$(PWD):/app\"` This means we're going to make the current directory\n  available in the container at `/app`.\n- `-w /app` This means we want to run our command inside of `/app`\n- `-u \"$(shell id -u):$(shell id -g)\" ` This means the user id and group id\n  of the process in the container should be equal to the user id and group id\n  of the host system. This is important on Linux because of the mount, with\n  docker for macOS this setting is actually optional.\n- `rust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64`\n  This specifies one specific Rust image by it's checksum. This is important to\n  document which compiler was used to build the binary. If you use the same\n  compiler you're also going to get a 100% identical binary (note this might\n  not be the case with more complex builds).\n- `cargo build --release --locked` This is the command we're running inside the\n  container. This is compiling the binary with optimizations from the release\n  profile.\n- `--locked` This option explicitly says the dependencies in the Cargo.lock\n  file must be used (none, in our case).\n- `--target=x86_64-unknown-linux-musl` This specifies the target system we want\n  to support, in our case that's the cpu architecture and linux with musl libc.\n  This currently implies statically linked builds in the rust world.\n\n## `docker:`\n\nThis builds the Docker image.\n\n- `sudo buildah` This means we're going to run [`buildah`](https://buildah.io/)\n  as root. `buildah` is a tool to build container images, its less known than\n  docker but has a unique feature that we're going to use here. The final image\n  can be used with docker too.\n- `bud` This is short for build-using-dockerfile, it means we're going to\n  execute the instructions in our [`Dockerfile`](dockerfile.md).\n- `--timestamp 0` This causes buildah to hardcode the build time to `1970-01-01\n  00:00:00`. Usually the current time is used instead, which would make the\n  image indeterministic.\n- `--tag asdf` This means our newly built image should be tagged with the name\n  `asdf`.\n\n## `src.tgz:`\n\nThis snapshots all the source code from this git commit into an archive. This\nis only needed for the Arch Linux package.\n\n- `git archive` This subcommand creates an archive that contains all the code\n  from a given commit.\n- `-o src.tgz` This specifies the file the archive should be written to.\n- `HEAD` Refers to the commit we've currently checked out.\n\n## `.PHONY: build docker`\n\nThis means `build` and `docker` are target names, not file names. The commands\nshould execute even if a file with that name already exists.\n"
  },
  {
    "path": "writeups/pkgbuild.md",
    "content": "# `PKGBUILD`\n\nThis file is only used if you're following the \"Reproducing the Arch Linux\npackage\" instructions.\n\n```sh\npkgname=i-probably-didnt-backdoor-this\npkgver=0.1.1\npkgrel=1\narch=('x86_64')\nmakedepends=('cargo')\nsource=(src.tgz)\nsha256sums=(SKIP)\n\nbuild() {\n    cargo build --release --locked\n}\n\npackage() {\n    install -Dm 755 target/release/asdf -t \"${pkgdir}/usr/bin/\"\n}\n```\n\nThis is the bare minimum to create a working package, even though it doesn't\nmeet the Arch Linux packaging standards (namcap is going to print some warnings\nabout this).\n\n```sh\npkgname=i-probably-didnt-backdoor-this\npkgver=0.1.1\npkgrel=1\narch=('x86_64')\n```\n\nThese fields are required in a PKGBUILD, it contains the package name and the\npackage version. `pkgrel=` is a \"revision\" in case we need to release a new\npackage for the same upstream version. `arch=` is a list of supported\narchitectures, for simplicity we set this to just `x86_64`.\n\n```sh\nmakedepends=('cargo')\n```\n\nIn addition to base-devel, which we can assume is always installed in the build\ncontainer, we also need the rust build system. Note that we don't specify which\nversion we want, for the initial build this is automatically going to resolve\nto \"the latest in Arch Linux\", for our rebuild we're going to pick the one\nthat's specified in the `.BUILDINFO` file of the package we want to reproduce.\nThere's an in-depth explanation in the [Arch Linux package\nwriteup](archlinux.md).\n\n```sh\nsource=(src.tgz)\nsha256sums=(SKIP)\n```\n\nThese are the source inputs, `src.tgz` is a tarball of this repository that\nwe're going to generate with `git archive` as described in the\n[`Makefile`](makefile.md).\n\n```sh\nbuild() {\n    cargo build --release --locked\n}\n```\n\nThis function implements the actual build. `--release` specifies the binary\nshould be built with the [standard release\nprofile](https://doc.rust-lang.org/cargo/reference/profiles.html#release).\n`--locked` means the build MUST use the dependencies defined in\n[`Cargo.lock`](cargo-lock.md).\n\n```sh\npackage() {\n    install -Dm 755 target/release/asdf -t \"${pkgdir}/usr/bin/\"\n}\n```\n\nAfter the build this function implements how the package should be created.\n\n- `install -Dm 755` means we want to copy a file, all directories in the\n  destination path should be created as needed, and `755` are the permissions\n  the file should have. This translates to \"read/write/execute for root,\n  read/execute for everybody else\".\n- `target/release/asdf` this is the file that was compiled in `build()` that we\n  want to ship in our package.\n- `-t \"${pkgdir}/usr/bin/\"` this means the file should be copied into the\n  `/usr/bin/` folder of our package. `install` is going to keep the filename.\n"
  }
]