├── .env.example ├── .envrc.example ├── .gitignore ├── README.md ├── Vagrantfile ├── ansible.cfg ├── doc ├── Debian_9.x.md ├── Ubuntu_18.04.x.md └── macOS.md ├── docs └── gpg_keys.md ├── forward_gpg_agent.sh ├── gitian.yml ├── local └── README.md ├── requirements-pip.lock └── roles ├── common ├── defaults │ └── main.yml ├── files │ ├── 02periodic │ └── 50unattended-upgrades ├── handlers │ └── main.yml ├── tasks │ ├── add_github_ssh_hostkey.yml │ ├── auto_upgrades.yml │ ├── hostname.yml │ ├── main.yml │ ├── make_swap.yml │ ├── motd.yml │ ├── packages.yml │ ├── repartition.yml │ ├── update_everything.yml │ └── vim.yml └── templates │ ├── log-core-dump.j2 │ └── motd.j2 └── gitian ├── defaults └── main.yml ├── files └── explode_yaml_file.py ├── meta └── main.yml ├── tasks ├── gpg.yml ├── keys.yml └── main.yml └── templates ├── gitian-build.py ├── gitian-lxc ├── gpg.conf ├── lxc-net ├── profile └── rc.local /.env.example: -------------------------------------------------------------------------------- 1 | GPG_KEY_ID=3F14A629C06FA31D59C64FE93F0C2117D53A4A49 2 | GPG_KEY_NAME=hpotter 3 | AXE_GIT_REPO_URL=https://github.com/axerunners/axe 4 | AXE_VERSION=v1.5.0.1 5 | -------------------------------------------------------------------------------- /.envrc.example: -------------------------------------------------------------------------------- 1 | source_up 2 | dotenv 3 | 4 | export GIT_NAME=`git config user.name` 5 | export GIT_EMAIL=`git config user.email` 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .envrc 3 | .vagrant/* 4 | *.swp 5 | gitian.sigs/* 6 | local/* 7 | !local/README.md 8 | axecore-binaries/* 9 | *.log 10 | .DS_Store 11 | *.sdk.tar.gz 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AXE deterministic builds 2 | ========================== 3 | 4 | 5 | 6 | This is a deterministic build environment for [AXE](https://github.com/AXErunners/axe) that uses [Gitian](https://gitian.org/). 7 | 8 | Gitian provides a way to be reasonably certain that the AXE executables are really built from the exact source on GitHub and have not been tampered with. It also makes sure that the same, tested dependencies are used and statically built into the executable. 9 | 10 | Multiple developers build from source code by following a specific descriptor ("recipe"), cryptographically sign the result, and upload the resulting signature. These results are compared and only if they match is the build accepted. 11 | 12 | More independent Gitian builders are needed, which is why this guide exists. 13 | 14 | Requirements 15 | ------------ 16 | 17 | 6GB of RAM, four cores. 18 | 19 | Note: This project uses VirtualBox to run a virtual machine. If you are running this inside a 20 | virtual machine, you'll likely need to enable a feature such as “nested virtualization”, “VT-x”, or 21 | similar in your virtualization software's settings for that virtual machine. 22 | 23 | 24 | Install Dependencies 25 | -------------------- 26 | 27 | If you're using one of the following platforms, see the linked instructions for that platform: 28 | 29 | - [Debian 9.x](doc/Debian_9.x.md) 30 | - [Ubuntu 18.04.x](doc/Ubuntu_18.04.x.md) 31 | - [macOS](doc/macOS.md) 32 | 33 | 34 | If you're not using one of the platforms that we have specific instructions for, this is the list of 35 | dependencies we want. Please document the steps involved and we can add another platform to the list 36 | above! 37 | 38 | - [Git](https://git-scm.com/) 39 | - [VirtualBox](https://www.virtualbox.org/) 40 | - [Vagrant](https://www.vagrantup.com/) 2.0.3 or higher 41 | - [GnuPG](https://www.gnupg.org/) 2.x (2.11.18 or greater) 42 | - [Python](https://www.python.org/) 3.x (with `venv` support in case that is packaged separately) 43 | - [direnv](https://direnv.net/) (Optional/Recommended) 44 | 45 | 46 | Download Apple SDK 47 | ------------------ 48 | [Apple SDK](https://github.com/AXErunners/axe/blob/master/doc/README_osx.md) required for macOS builds. Place this tarball (`MacOSX10.11.sdk.tar.gz`) into _axe-gitian_ folder and _Ansible_ will copy it during the run. 49 | 50 | 51 | ## Configure git 52 | 53 | We want a configuration file in the home directory of the account you'll be working in. This will 54 | determine how you are identified on the projects you contribute to. These settings can be overridden 55 | on a per-project basis. 56 | 57 | Git provides some convenient command options for setting this up: 58 | 59 | ``` 60 | $ git config --global user.name "Harry Potter" 61 | $ git config --global user.email "hpotter@hogwarts.wiz" 62 | ``` 63 | 64 | Checking that this worked: 65 | 66 | ``` 67 | $ git config user.name 68 | Harry Potter 69 | $ git config user.email 70 | hpotter@hogwarts.wiz 71 | ``` 72 | 73 | This is all the git configuration needed for the steps below, but here is a good reference for 74 | further reading on configuring git: 75 | 76 | https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration 77 | 78 | 79 | 80 | ## Decide on an ssh keypair to use when uploading build signatures to github 81 | 82 | You can generate a keypair specifically for connecting to github like this: 83 | 84 | ``` 85 | $ ssh-keygen -t ed25519 -C "hpotter@hogwarts.wiz" -f ~/.ssh/github_id_rsa -N '' 86 | Generating public/private ed25519 key pair. 87 | Your identification has been saved in /Users/hpotter/.ssh/github_id_rsa. 88 | Your public key has been saved in /Users/hpotter/.ssh/github_id_rsa.pub. 89 | The key fingerprint is: 90 | SHA256:qBCOybcJkgs1xdNoocYlsZz3jNQhGgOymreQAQRyh0c hpotter@hogwarts.wiz 91 | The key's randomart image is: 92 | +--[ED25519 256]--+ 93 | |Oo*=E+. | 94 | |+=.%*o.. | 95 | |o %oo.. | 96 | |o@ = + . | 97 | |@o+.. + S | 98 | |o+ooo. | 99 | |. .o. | 100 | | | 101 | | | 102 | +----[SHA256]-----+ 103 | ``` 104 | 105 | Some explanation of the arguments used in the above example: 106 | 107 | ``` 108 | -t ed25519 Use a key type of ed25519 109 | 110 | -C "hpotter@hogwarts.wiz" Provide an identity to associate with the key (default is 111 | user@host in the local environment) 112 | 113 | -f ~/.ssh/github_id_rsa Path to the private key to generate. The corresponding public key 114 | will be saved at ~/.ssh/github_id_rsa.pub 115 | 116 | -N '' Passphrase for the generated key. An empty string as shown here 117 | means save the private key unencrypted. 118 | ``` 119 | 120 | 121 | 122 | # Set up your ssh keypair for use with github 123 | 124 | [Add the new key to your github account.](https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/) 125 | 126 | Add an entry to `~/.ssh/config` (create this file if necessary) telling ssh to use the keypair you 127 | generated above when connecting to github.com. 128 | 129 | 130 | For instance: 131 | 132 | ``` 133 | Host github.com 134 | User harrypotter 135 | PreferredAuthentications publickey 136 | IdentityFile /home/hpotter/.ssh/github_id_rsa 137 | AddKeysToAgent yes 138 | ``` 139 | 140 | The 'User' entry should match your github username. 141 | 142 | If using macOS, the IdentityFile path will be: 143 | 144 | ``` 145 | /Users/yourusername/.ssh/github_id_rsa 146 | ``` 147 | 148 | If you do generate a new ssh config file you'll need to set its permission bits appropriately. On 149 | a Unix system you may do so with a command like this: 150 | 151 | ``` 152 | chmod 400 ~/.ssh/config 153 | ``` 154 | 155 | Test that ssh will successfully use your new key to connect to github. 156 | 157 | ``` 158 | $ ssh -T git@github.com 159 | The authenticity of host 'github.com (192.30.253.112)' can't be established. 160 | RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8. 161 | Are you sure you want to continue connecting (yes/no)? yes 162 | Warning: Permanently added 'github.com,192.30.253.112' (RSA) to the list of known hosts. 163 | Hi harrypotter! You've successfully authenticated, but GitHub does not provide shell access. 164 | $ 165 | ``` 166 | 167 | 168 | 169 | ## Clone this git project on your machine 170 | 171 | From a location where you want to place your local clone of this repository (e.g. `~/Projects`). If 172 | there's a possibility you'll want to make and contribute changes, consider forking the repository 173 | and cloning from your fork. For example: 174 | 175 | ``` 176 | git clone git@github.com:harrypotter/axe-gitian.git 177 | ``` 178 | 179 | cd into the project repo 180 | 181 | ``` 182 | $ cd axe-gitian 183 | axe-gitian 184 | ``` 185 | 186 | 187 | ## Copy example environment configuration files 188 | 189 | The files `.env.example` and `.envrc.example` are tracked in the repo as example configurations you 190 | should be able to use to get started. The filenames `.env` and `.envrc` are `.gitignore`'d to allow 191 | you to easily make local customizations that don't show up as untracked changes. 192 | 193 | Note that `.envrc` is probably only useful if you are using `direnv`. If you're not, you can ignore 194 | that file and the places below that talk about it, and use your preferred way of managing 195 | environment variables instead. 196 | 197 | ``` 198 | axe-gitian$ cp .env.example .env 199 | axe-gitian$ cp .envrc.example .envrc 200 | direnv: error .envrc is blocked. Run `direnv allow` to approve its content. 201 | axe-gitian$ 202 | ``` 203 | 204 | More on that above message in the following section... 205 | 206 | 207 | 208 | ## Enable auto-execution of .envrc 209 | 210 | If you installed and activated `direnv`, it will detect when `.envrc` is created in your current 211 | directory, as shown above. As a security precaution, it won't automatically run it without your 212 | approval (to prevent untrusted code from doing something malicious). Let's take a look at what's in 213 | the file: 214 | 215 | ``` 216 | axe-gitian$ cat .envrc 217 | source_up 218 | dotenv 219 | 220 | export GIT_NAME=`git config user.name` 221 | export GIT_EMAIL=`git config user.email` 222 | direnv: error .envrc is blocked. Run `direnv allow` to approve its content. 223 | axe-gitian$ 224 | ``` 225 | 226 | Some explanation of the lines in the above `.envrc` file: 227 | 228 | ``` 229 | `source_up` Load any .envrc higher up in the folder structure. So if for 230 | example you place an `.envrc` in your home directory, variables 231 | set there will still be available within this project, rather 232 | than being overridden by this project's `.envrc`. 233 | 234 | `dotenv` Set the environment variables defined in `.env`. Think of 235 | `.envrc` as code (it runs in a bash interpreter with some extra 236 | functions added) and `.env` as data (you can basically just set 237 | literal values, and each update to it doesn't require approval). 238 | 239 | 240 | export GIT_NAME=`git config user.name` 241 | export GIT_EMAIL=`git config user.email` 242 | 243 | Use your local git configuration values for the name and email 244 | that will be used to add build signatures inside the virtual 245 | environment. 246 | ``` 247 | 248 | 249 | If you're ok with running `.envrc`, follow the directions in the prompt to allow it. 250 | 251 | ``` 252 | axe-gitian$ echo $AXE_GIT_REPO_URL 253 | 254 | direnv: error .envrc is blocked. Run `direnv allow` to approve its content. 255 | axe-gitian$ direnv allow 256 | direnv: loading .envrc 257 | direnv: export +GIT_EMAIL +GIT_NAME +GPG_KEY_ID +GPG_KEY_NAME +AXE_GIT_REPO_URL +AXE_VERSION 258 | axe-gitian$ echo $AXE_GIT_REPO_URL 259 | https://github.com/axerunners/axe 260 | axe-gitian$ 261 | ``` 262 | 263 | A variable defined in `.env` is now active in our environment. If we leave this project, it is 264 | unloaded. When we return, it is reloaded: 265 | 266 | ``` 267 | axe-gitian$ cd .. 268 | direnv: unloading 269 | $ echo $AXE_GIT_REPO_URL 270 | 271 | $ cd axe-gitian/ 272 | direnv: loading .envrc 273 | direnv: export +GIT_EMAIL +GIT_NAME +GPG_KEY_ID +GPG_KEY_NAME +AXE_GIT_REPO_URL +AXE_VERSION 274 | axe-gitian$ echo $AXE_GIT_REPO_URL 275 | https://github.com/axerunners/axe 276 | axe-gitian$ 277 | ``` 278 | 279 | Project-specific environment settings will come in handy in the next step, when we'll create an 280 | isolated python virtual environment specifically for use with this project. 281 | 282 | 283 | 284 | ## Create a python virtual environment for this project 285 | 286 | Note: The main purpose of this part is to get a current version of ansible, and keep it locally 287 | within this project. If you already installed ansible (e.g. from an OS package manager like apt), 288 | you can skip this part and the following parts about pip and pip packages. 289 | 290 | When creating a virtual environment, call the python executable you want the virtual environment to 291 | use. The location and version will depend on your specific setup -- your OS may provide a suitably 292 | current python interpreter, or you may have built and installed one yourself. If it's in your PATH, 293 | a command like `type python3` should tell you where it is installed on your system. For example: 294 | 295 | ``` 296 | axe-gitian$ type python3 297 | python3 is /usr/local/bin/python3 298 | axe-gitian$ /usr/local/python3 --version 299 | Python 3.7.4 300 | ``` 301 | 302 | You may also want to check if the `python3` in `PATH` is a symlink to a versioned location, if you 303 | are using a system (like `brew`) that can manage multiple installed versions. This way, our virtual 304 | environment will remain pinned to a specific python version even after a newer python version is 305 | installed later. 306 | 307 | ``` 308 | $ ls -n /usr/local/bin/python3 309 | lrwxr-xr-x 1 501 20 34 Mar 30 09:35 /usr/local/bin/python3 -> ../Cellar/python/3.7.4/bin/python3 310 | ``` 311 | 312 | We can use python's built-in `venv` module to create a virtual environment: 313 | 314 | ``` 315 | axe-gitian$ /usr/local/Cellar/python/3.7.4/bin/python3 -m venv local/python_v3.7.4_venv 316 | ``` 317 | 318 | Translation: "Create a virtual environment at ./local/python_v3.7.4_venv". 319 | 320 | The project subdirectory `local` is `.gitignored` to provide a convenient location for files we 321 | don't want to commit and track in version control. 322 | 323 | You should now have a tree of directories and files in `local/python_v3.7.4_venv`: 324 | 325 | ``` 326 | axe-gitian$ ls -F local/python_v3.7.4_venv/ 327 | bin/ include/ lib/ pyvenv.cfg 328 | ``` 329 | 330 | Inside the `bin` directory, among other things, are the entries `python` and `python3`, which are 331 | symlinks that point back to the `python3` executable we used to create this environment: 332 | 333 | ``` 334 | axe-gitian$ ls -F local/python_v3.7.4_venv/bin/ 335 | activate activate.fish easy_install-3.7* pip3* python@ 336 | activate.csh easy_install* pip* pip3.7* python3@ 337 | ``` 338 | 339 | A python virtual environment is 'active' if the python interpreter being executed is run from its 340 | path inside the environment's `bin` directory. Even though the file being executed is the same 341 | whether run directly or via a symlink, it pays attention to the path of the command that was used to 342 | run it. 343 | 344 | An `activate` script is provided, and you can use that, but if you're using `direnv` you can set up 345 | a simple automatic activation for the project directory by adding the following line to `.envrc`: 346 | 347 | ``` 348 | load_prefix local/python_v3.7.4_venv 349 | ``` 350 | 351 | The command `load_prefix` is provided by `direnv` to modify a whole set of common "path" variables 352 | (including PATH) according to a common unix pattern. 353 | 354 | Let's add that line now: 355 | 356 | ``` 357 | axe-gitian$ echo "load_prefix local/python_v3.7.4_venv" >> .envrc 358 | direnv: error .envrc is blocked. Run `direnv allow` to approve its content. 359 | axe-gitian$ direnv allow 360 | direnv: loading .envrc 361 | direnv: export +CPATH +GIT_EMAIL +GIT_NAME +GPG_KEY_ID +GPG_KEY_NAME +LD_LIBRARY_PATH +LIBRARY_PATH +MANPATH +PKG_CONFIG_PATH +AXE_GIT_REPO_URL +AXE_VERSION ~PATH 362 | axe-gitian$ 363 | ``` 364 | 365 | When the content of `.envrc` is changed, it needs to be approved again (another security 366 | precaution). Then, several variables were set or updated to add paths within our virtual environment 367 | directory at the front (left side) of the list. Let's look at PATH and its effect on which `python` 368 | locations we default to: 369 | 370 | ``` 371 | axe-gitian$ echo $PATH 372 | /Users/harrypotter/Projects/axe-gitian/local/python_v3.7.4_venv/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games 373 | axe-gitian$ type python 374 | python is /Users/harrypotter/Projects/axe-gitian/local/python_v3.7.4_venv/bin/python 375 | axe-gitian$ type python3 376 | python3 is /Users/harrypotter/Projects/axe-gitian/local/python_v3.7.4_venv/bin/python3 377 | ``` 378 | 379 | Since the `python` and `python3` commands will now run from the locations we've installed into our 380 | project's virtual environment while we are in the project directory, we can consider the virtual 381 | environment active when using a shell at (or below) that location. 382 | 383 | 384 | 385 | ## Upgrade pip 386 | 387 | `pip3` has a command to upgrade itself. Let's go ahead and run that: 388 | 389 | ``` 390 | axe-gitian % pip3 install --upgrade pip 391 | Collecting pip 392 | [...] 393 | Successfully uninstalled pip-20.1.1 394 | Successfully installed pip-20.2.4 395 | ``` 396 | 397 | 398 | 399 | ## Install pip packages 400 | 401 | We have some dependencies to install as python packages, using the pip package manager installed 402 | above. The set we need, with version numbers managed via git, is in `requirements-pip.lock`; we can 403 | run `pip3 install` with that file as input: 404 | 405 | ``` 406 | axe-gitian$ pip3 install --requirement requirements-pip.lock 407 | ``` 408 | 409 | Check that you can run `ansible` from the command line: 410 | 411 | ``` 412 | axe-gitian % ansible --version 413 | ansible 2.10.2 414 | [...] 415 | axe-gitian % 416 | ``` 417 | 418 | 419 | 420 | ## Decide on a gpg keypair to use for gitian 421 | 422 | You can generate a keypair specifically for axe gitian builds with a command like the one below. 423 | 424 | 425 | ``` 426 | axe-gitian$ gpg --quick-generate-key --batch --passphrase '' "Harry Potter (axe gitian) " 427 | gpg: key 3F0C2117D53A4A49 marked as ultimately trusted 428 | gpg: directory '/home/hpotter/.gnupg/openpgp-revocs.d' created 429 | gpg: revocation certificate stored as '/home/hpotter/.gnupg/openpgp-revocs.d/3F14A629C06FA31D59C64FE93F0C2117D53A4A49.rev' 430 | ``` 431 | 432 | Some explanation of the arguments used in the above example: 433 | 434 | --quick-generate-key --batch This combination of options allows options to be given on the 435 | command line. Other key generation options use interative 436 | prompts. 437 | 438 | --passphrase '' Passphrase for the generated key. An empty string as shown here 439 | means save the private key unencrypted. 440 | 441 | "Name (Comment) " The user id (also called uid) to associate with the generated 442 | keys. Concatenating a name, an optional comment, and an email 443 | address using this format is a gpg convention. 444 | 445 | 446 | You can check that the key was generated and added to your local gpg key database, and see its 447 | fingerprint value, like this: 448 | ``` 449 | axe-gitian$ gpg --list-keys 450 | /home/hpotter/.gnupg/pubring.kbx 451 | ---------------------------------- 452 | pub rsa2048 2018-04-23 [SC] [expires: 2020-04-22] 453 | 3F14A629C06FA31D59C64FE93F0C2117D53A4A49 454 | uid [ultimate] Harry Potter (axe gitian) 455 | sub rsa2048 2018-04-23 [E] 456 | ``` 457 | 458 | Update your `GPG_KEY_ID` and `GPG_KEY_NAME` variables in `.env` as follows: 459 | 460 | - `GPG_KEY_ID`: In the example output shown here, this is the 40 character string 461 | `3F14A629C06FA31D59C64FE93F0C2117D53A4A49`. Some versions of gpg may truncate this value, e.g. to 8 462 | or 16 characters. You should be able to use the truncated value. 463 | 464 | - `GPG_KEY_NAME`: This is passed as the '--signer' argument to Gitian, and used as the name of a 465 | directory for your signatures in our `gitian.sigs` repository. We suggest using the username portion 466 | of the email address associated with your GPG key. In our example this is `hpotter`. 467 | 468 | For more info about updating or revoking gpg keys, see [Notes on updating or revoking GPG keys](docs/gpg_keys.md) 469 | 470 | 471 | ## Install Vagrant plugins 472 | 473 | This project uses some 3rd party Vagrant plugins. These dependencies are specified in `Vagrantfile`. 474 | We can install them locally in the `.vagrant` directory with the following command: 475 | 476 | ``` 477 | axe-gitian$ vagrant plugin install --local 478 | ``` 479 | 480 | 481 | 482 | ## Configure the version of axe you want to build and sign 483 | 484 | Set the value of the `AXE_VERSION` variable in `.env` to point to the axe commit you want to 485 | create a signature for. Likely you want the name of a 486 | [git-tagged axe version](https://github.com/axerunners/axe/tags), usually the most recent released 487 | version. 488 | 489 | ## Provision a virtual machine 490 | 491 | From the project root directory, run: 492 | 493 | ``` 494 | axe-gitian$ vagrant up axe-build 495 | ``` 496 | 497 | This will provision a Gitian host virtual machine that uses a Linux container (LXC/Docker) guest to perform 498 | the actual builds. 499 | 500 | 501 | Load your ssh key into ssh-agent 502 | -------------------------------- 503 | 504 | Load your ssh key (for pushing signatures to github) into ssh-agent. The approach here is to allow 505 | programs in the axe-build VM to connect to ssh-agent to perform operations with the private key. 506 | This way, we don't need to copy ssh keys into the VM. 507 | 508 | If you don't already have an ssh-agent running you may need to start one. For example, you might be 509 | able to start one like this: 510 | 511 | ``` 512 | eval `ssh-agent -s` 513 | ``` 514 | 515 | You can verify that the key is loaded by 516 | running `ssh-add -l`. 517 | 518 | ``` 519 | axe-gitian$ ssh-add -l 520 | The agent has no identities. 521 | 522 | axe-gitian$ ssh-add ~/.ssh/github_id_rsa 523 | Identity added: /home/hpotter/.ssh/github_id_rsa (/home/hpotter/.ssh/github_id_rsa) 524 | 525 | axe-gitian$ ssh-add -l 526 | 4096 SHA256:4fFdwJ71VIpF5cW0dqrsU7jxjctaFcAKmdQZPEqR0Y4 /home/hpotter/.ssh/github_id_rsa (RSA) 527 | ``` 528 | 529 | 530 | SSH into the VM 531 | --------------- 532 | 533 | Vagrant should now show that the new VM is in the 'running' state: 534 | 535 | ``` 536 | axe-gitian$ vagrant status 537 | Current machine states: 538 | 539 | axe-build running (virtualbox) 540 | 541 | The VM is running. To stop this VM, you can run `vagrant halt` to 542 | shut it down forcefully, or you can run `vagrant suspend` to simply 543 | suspend the virtual machine. In either case, to restart it again, 544 | simply run `vagrant up`. 545 | ``` 546 | 547 | Use the `vagrant ssh` command to start a shell session in the VM. Once in that session, you can use 548 | ssh-add again to see that your forwarded key is available, and check that you can use that key to 549 | authenticate to github. 550 | 551 | ``` 552 | axe-gitian$ vagrant ssh axe-build 553 | [...] 554 | 555 | # on the virtualbox vm 556 | vagrant@axe-build:~$ ssh-add -l 557 | 4096 d1:43:75:a7:95:65:9e:d4:8e:57:d8:98:58:7d:92:4c /home/hpotter/.ssh/github_id_rsa (RSA) 558 | 559 | vagrant@axe-build:~$ ssh -T git@github.com 560 | Warning: Permanently added the RSA host key for IP address '192.30.253.112' to the list of known hosts. 561 | Hi harrypotter! You've successfully authenticated, but GitHub does not provide shell access. 562 | ``` 563 | 564 | 565 | Building AXE 566 | -------------- 567 | 568 | Once in a shell session in the VM, we're ready to run the gitian build. 569 | 570 | ``` 571 | # on the virtualbox vm 572 | # replace $SIGNER and $VERSION with your key and target version/branch/commit 573 | vagrant@axe-build:~$ ./gitian-build.py --setup $SIGNER $VERSION 574 | vagrant@axe-build:~$ ./gitian-build.py -b $SIGNER $VERSION # will start the build with unsigned output 575 | ``` 576 | 577 | The output from `gbuild` is informative. There are some common warnings which can be ignored, e.g. if you get an intermittent privileges error related to LXC then just execute the script again. The most important thing is that one reaches the step which says `Running build script (log in var/build.log)`. If not, then something else is wrong and you should let us know. 578 | 579 | Take a look at the variables of `~/gitian-build.py` and get familiar with its functioning, as it can handle most tasks. 580 | 581 | It's also a good idea to regularly `git pull` on this repository to obtain updates and re-run the entire VM provisioning for each release, to ensure current and consistent state for your builder. 582 | 583 | Generating and uploading signatures 584 | ----------------------------------- 585 | 586 | Signatures can be verified by running `gitian-build.py --verify`, but set `build=false` in the script to skip building. Run a `git pull` beforehand on `gitian.sigs` so you have the latest. The provisioning includes a task which imports Axe developer public keys to the Vagrant user's keyring and sets them to ultimately trusted, but they can also be found at `contrib/gitian-downloader` within the AXE source repository. 587 | 588 | After the build successfully completes, the gitian command `gsign` will be called, which will 589 | generate signatures, and a commit will be added. 590 | 591 | Fork the [axerunners/gitian.sigs](https://github.com/axerunners/gitian.sigs) repository by following the link 592 | and clicking "fork". 593 | 594 | Now you can cd into the gitian.sigs directory, set the repository to point to your fork of 595 | [axerunners/gitian.sigs](https://github.com/axerunners/gitian.sigs), push 596 | your updates to a branch, and then make a pull request on github. 597 | 598 | ``` 599 | cd gitian.sigs 600 | git remote rename origin upstream 601 | git remote add origin git@github.com:harrypotter/gitian.sigs.git 602 | git checkout -b v1.5.0.0 603 | git push origin v1.5.0.0 604 | ``` 605 | 606 | 607 | Working with GPG 608 | ---------------- 609 | 610 | We provide two options for automatically importing keys into the VM, or you may choose to copy them manually. GPG keys are needed to sign the manifests which get pushed to [gitian.sigs](https://github.com/axerunners/gitian.sigs). 611 | 612 | GPG is tricky, especially if you use a smartcard and can't copy the secret key. We have a script intended to forward the gpg-agent socket into the VM, `forward_gpg_agent.sh`, but it is not currently working. If you want your full keyring to be available, you can use the following workaround involving `sshfs` and synced folders: 613 | 614 | vagrant plugin install vagrant-sshfs 615 | 616 | Uncomment the line beginning with `gitian.vm.synced_folder "~/.gnupg"` in `Vagrantfile`. Ensure the destination mount point is empty. Then run: 617 | 618 | vagrant sshfs --mount axe-build 619 | 620 | Vagrant synced folders may also work natively with `vboxfs` if you install VirtualBox Guest Additions into the VM from `contrib`, but that's not as easy to setup. 621 | 622 | 623 | Copying files 624 | ------------- 625 | 626 | To copy files to the VM: `vagrant scp file_on_host.txt :file_on_vm.txt` 627 | 628 | To copy files from the VM: `vagrant scp :file_on_vm.txt file_on_host.txt` 629 | 630 | Other notes 631 | ----------- 632 | 633 | Port 2200 on the host machine should be forwarded to port 22 on the guest virtual machine. 634 | 635 | The automation and configuration management assumes that VirtualBox will assign the IP address `10.0.2.15` to the Gitian host Vagrant VM. 636 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | Vagrant.configure(2) do |config| 4 | 5 | config.vagrant.plugins = { 6 | "vagrant-disksize" => {"version" => "0.1.3"}, 7 | "vagrant-scp" => {"version" => "0.5.7"} 8 | } 9 | 10 | config.ssh.forward_agent = true 11 | config.disksize.size = '24GB' 12 | config.vm.define 'axe-build', autostart: false do |gitian| 13 | gitian.vm.box = "debian/stretch64" 14 | gitian.vm.box_version = "9.12.0" 15 | gitian.vm.network "forwarded_port", guest: 22, host: 2200, auto_correct: true 16 | gitian.vm.provision "ansible" do |ansible| 17 | ansible.playbook = "gitian.yml" 18 | ansible.verbose = 'vvv' 19 | ansible.raw_arguments = Shellwords.shellsplit(ENV['ANSIBLE_ARGS']) if ENV['ANSIBLE_ARGS'] 20 | end 21 | gitian.vm.provider "virtualbox" do |v| 22 | v.name = "axe-build" 23 | v.memory = 4096 24 | v.cpus = 2 25 | end 26 | # gitian.vm.synced_folder "~/.gnupg", "/home/vagrant/.gnupg", type: "sshfs" 27 | # gitian.vm.synced_folder "./gitian.sigs", "/home/vagrant/gitian.sigs", create: true 28 | # gitian.vm.synced_folder "./axecore-binaries", "/home/vagrant/axecore-binaries", create: true 29 | gitian.vm.post_up_message = "AXE deterministic build environment started." 30 | end 31 | 32 | end 33 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = inventory 3 | retry_files_enabled = False 4 | roles_path = roles 5 | host_key_checking = False 6 | timeout = 60 7 | 8 | [ssh_connection] 9 | ssh_args = -o ControlMaster=auto -o ControlPersist=300s -o ConnectTimeout=60 -o IdentitiesOnly=yes 10 | pipelining = True 11 | scp_if_ssh = True 12 | -------------------------------------------------------------------------------- /doc/Debian_9.x.md: -------------------------------------------------------------------------------- 1 | # Dependency installation steps for Debian GNU/Linux 9.x (stretch) 2 | 3 | This document assumes you are starting from a fresh install of Debian in the 9.x series. 4 | 5 | Most recently tested 2019-03-21 with the following debian release: 6 | 7 | ``` 8 | $ lsb_release --description 9 | Description: Debian GNU/Linux 9.8 (stretch) 10 | ``` 11 | 12 | 13 | 14 | # Install VirtualBox 15 | 16 | Virtualbox is the configured VM provider in this project's Vagrantfile. 17 | 18 | First, check whether virtualbox is installed. Some systems may have it already: 19 | 20 | ``` 21 | $ virtualbox --help 22 | Oracle VM VirtualBox VM Selector v6.0.4 23 | [...] 24 | ``` 25 | 26 | (If it is installed, you can probably skip this step. Note that virtualbox installs linux kernel 27 | modules which need to be kept in sync with the virtualbox apt package, so if you decide to change to 28 | a different version, be sure to uninstall completely (including the kernel modules) before 29 | reinstalling.) 30 | 31 | Add Oracle's VirtualBox apt repository to your system's apt sources: 32 | 33 | ``` 34 | sudo apt-add-repository "deb http://download.virtualbox.org/virtualbox/debian $(lsb_release -sc) contrib" 35 | ``` 36 | 37 | Verify that the source was added: 38 | 39 | ``` 40 | $ grep -iR virtualbox /etc/apt/sources.list* 41 | /etc/apt/sources.list:deb http://download.virtualbox.org/virtualbox/debian stretch contrib 42 | /etc/apt/sources.list:# deb-src http://download.virtualbox.org/virtualbox/debian stretch contrib 43 | ``` 44 | 45 | Download and register the public gpg key used by Oracle to secure the above 46 | repository: 47 | 48 | ``` 49 | $ wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add - 50 | OK 51 | ``` 52 | 53 | Verify that the key was added 54 | 55 | ``` 56 | $ apt-key list "B9F8 D658 297A F3EF C18D 5CDF A2F6 83C5 2980 AECF" 57 | pub rsa4096 2016-04-22 [SC] 58 | B9F8 D658 297A F3EF C18D 5CDF A2F6 83C5 2980 AECF 59 | uid [ unknown] Oracle Corporation (VirtualBox archive signing key) 60 | sub rsa4096 2016-04-22 [E] 61 | ``` 62 | 63 | Update your local apt package metadata 64 | 65 | ``` 66 | $ sudo apt update 67 | [...] 68 | ``` 69 | 70 | This command will show the available versions of virtualbox from the apt 71 | repository: 72 | 73 | ``` 74 | $ sudo apt install virtualbox 75 | Reading package lists... Done 76 | Building dependency tree 77 | Reading state information... Done 78 | Package virtualbox is a virtual package provided by: 79 | virtualbox-6.0 6.0.4-128413~Debian~stretch 80 | virtualbox-5.2 5.2.26-128414~Debian~stretch 81 | virtualbox-5.1 5.1.38-122592~Debian~stretch 82 | virtualbox-5.0 5.0.40-115130~Debian~stretch 83 | You should explicitly select one to install. 84 | 85 | E: Package 'virtualbox' has no installation candidate 86 | ``` 87 | 88 | Decide on the version you want and specify the version number to install it: 89 | 90 | ``` 91 | $ sudo apt install virtualbox-6.0 -y 92 | [...] 93 | ``` 94 | 95 | Source: https://www.virtualbox.org/wiki/Linux_Downloads#Debian-basedLinuxdistributions 96 | 97 | Most recently tested 2019-03-21 with the following virtualbox release: 98 | 99 | ``` 100 | $ virtualbox --help 101 | Oracle VM VirtualBox VM Selector v6.0.4 102 | [...] 103 | ``` 104 | 105 | 106 | 107 | ## Install git 108 | 109 | ``` 110 | $ sudo apt install git 111 | ``` 112 | 113 | Most recently tested 2019-03-21 with the following git release: 114 | 115 | ``` 116 | $ git --version 117 | git version 2.11.0 118 | ``` 119 | 120 | 121 | 122 | # Install Vagrant 2.0.3 or higher 123 | 124 | As of this writing, the Vagrant version that Debian uses in its "stretch" release is 1.9.x so we 125 | suggest getting a package from Vagrant's web site: 126 | 127 | ``` 128 | wget -c https://releases.hashicorp.com/vagrant/2.2.4/vagrant_2.2.4_x86_64.deb 129 | sudo dpkg -i vagrant_2.2.4_x86_64.deb 130 | rm vagrant_2.2.4_x86_64.deb 131 | ``` 132 | 133 | Most recently tested 2019-03-21 with the following vagrant release: 134 | 135 | ``` 136 | $ vagrant --version 137 | Vagrant 2.2.4 138 | ``` 139 | 140 | 141 | 142 | # Install venv support 143 | 144 | `venv` is a python module used to create isolated project-specific environments, so that projects on 145 | the same computer can each use their own version of the python executable and their own set of 146 | installed python modules. 147 | 148 | `python3-venv` is an `apt` package that includes support for using the `venv` python module. 149 | 150 | ``` 151 | sudo apt install python3-venv 152 | ``` 153 | 154 | Most recently tested 2019-03-05 with the following python3-venv release: 155 | 156 | ``` 157 | $ dpkg --status python3-venv | grep Version 158 | Version: 3.5.3-1 159 | ``` 160 | 161 | 162 | 163 | # Install direnv (Optional/Recommended) 164 | 165 | This tool sets and unsets environment variables as you change directories in a shell session, 166 | providing a convenient facility for setting up project-specific configuration. 167 | 168 | ``` 169 | sudo apt install direnv 170 | ``` 171 | 172 | To activate direnv when starting bash (the default shell on Debian 9), add the following line to the 173 | end of `~/.bashrc`: 174 | 175 | ``` 176 | eval "$(direnv hook bash)" 177 | ``` 178 | 179 | direnv works by incorporating a call to `_direnv_hook` in the `PROMPT_COMMAND` shell variable. You 180 | can check that this was done by starting a new bash session and checking whether that value is 181 | present: 182 | 183 | ``` 184 | $ echo $PROMPT_COMMAND 185 | _direnv_hook; 186 | ``` 187 | 188 | direnv also supports several other shells -- zsh, fish, tcsh, and elvish as of this writing. Its 189 | website includes instructions for enabling each of the shells it supports. 190 | 191 | Most recently tested 2019-03-21 with the following direnv release: 192 | 193 | ``` 194 | $ direnv --help 195 | direnv v2.10.0 196 | [...] 197 | ``` 198 | -------------------------------------------------------------------------------- /doc/Ubuntu_18.04.x.md: -------------------------------------------------------------------------------- 1 | # Dependency installation steps for Ubuntu 18.04.x LTS (Bionic Beaver) 2 | 3 | This document assumes you are starting from a fresh install of Ubuntu in the 18.04.x series. 4 | 5 | 6 | ## Install Git, VirtualBox, and rng-tools 7 | 8 | ``` 9 | $ sudo apt install git virtualbox rng-tools 10 | ``` 11 | 12 | 13 | 14 | # Install Vagrant 2.0.3 or higher 15 | 16 | As of this writing, the vagrant version that Ubuntu 18.04 uses is 2.0.2 so we suggest a later 17 | release in the 2.0.x series. 18 | 19 | ``` 20 | wget -c https://releases.hashicorp.com/vagrant/2.2.4/vagrant_2.2.4_x86_64.deb 21 | sudo dpkg -i vagrant_2.2.4_x86_64.deb 22 | rm vagrant_2.2.4_x86_64.deb 23 | ``` 24 | 25 | Most recently tested 2019-03-26 with the following vagrant release: 26 | 27 | ``` 28 | $ vagrant --version 29 | Vagrant 2.2.4 30 | ``` 31 | 32 | 33 | 34 | ## Choice: Install Ansible via apt now or pip later 35 | 36 | You can install ansible to a system-wide location using Ubuntu's apt tool, which will be a less 37 | current version, with infrequent updates, or choose another method described later to install it via 38 | a python package in a project-local virtual environment. The apt method is a bit easier, while the 39 | python method is ansible's native distribution channel and will be more current and more frequently 40 | updated. 41 | 42 | If you choose the apt option, run this command: 43 | 44 | ``` 45 | $ sudo apt install ansible 46 | ``` 47 | 48 | If you choose the python/pip option, run this command: 49 | 50 | ``` 51 | $ sudo apt install python3-venv 52 | ``` 53 | 54 | 55 | 56 | # Install direnv (Optional/Recommended) 57 | 58 | This tool sets and unsets environment variables as you change directories in a shell session, 59 | providing a convenient facility for setting up project-specific configuration. 60 | 61 | ``` 62 | sudo apt install direnv 63 | ``` 64 | 65 | To activate direnv when starting bash (the default shell on Ubuntu 18.04), add the following line to 66 | the end of `~/.bashrc`: 67 | 68 | ``` 69 | eval "$(direnv hook bash)" 70 | ``` 71 | 72 | direnv works by incorporating a call to `_direnv_hook` in the `PROMPT_COMMAND` shell variable. You 73 | can check that this was done by starting a new bash session and checking whether that value is 74 | present: 75 | 76 | ``` 77 | $ echo $PROMPT_COMMAND 78 | _direnv_hook; 79 | ``` 80 | 81 | direnv also supports several other shells -- zsh, fish, tcsh, and elvish as of this writing. Its 82 | website includes instructions for enabling each of the shells it supports. 83 | 84 | 85 | 86 | ## Headless notes 87 | 88 | Server instances should force GPG client to use TTY by adding following line in `~/.bashrc`: 89 | 90 | ``` 91 | export GPG_TTY=$(tty) 92 | ``` 93 | 94 | 95 | 96 | ## Versions 97 | 98 | Most recently tested 2018-03-26 with the following versions: 99 | 100 | 101 | ### Ubuntu 102 | 103 | ``` 104 | $ lsb_release --description 105 | Description: Ubuntu 18.04 LTS 106 | ``` 107 | 108 | 109 | ### Git 110 | 111 | ``` 112 | $ git --version 113 | git version 2.17.1 114 | ``` 115 | 116 | 117 | ### VirtualBox 118 | 119 | ``` 120 | $ virtualbox --help 121 | Oracle VM VirtualBox Manager 5.2.18_Ubuntu 122 | ... 123 | ``` 124 | 125 | 126 | ### Ansible 127 | 128 | ``` 129 | $ ansible --version 130 | ansible 2.5.1 131 | [...] 132 | ``` 133 | 134 | 135 | ### direnv 136 | 137 | ``` 138 | $ direnv --help 139 | direnv v2.15.0 140 | [...] 141 | ``` 142 | -------------------------------------------------------------------------------- /doc/macOS.md: -------------------------------------------------------------------------------- 1 | # Dependency installation steps for macOS 2 | 3 | This document assumes you are starting from a fresh install of macOS. 4 | 5 | Most recently tested 2020-10-28 with the following macOS release: 6 | 7 | ``` 8 | % sw_vers 9 | ProductName: Mac OS X 10 | ProductVersion: 10.15.7 11 | BuildVersion: 19H2 12 | ``` 13 | 14 | 15 | 16 | ## Make sure Git is installed 17 | 18 | macOS includes git, so you should already have that. It may prompt you to set up developer tools if 19 | you're using it for the first time. 20 | 21 | Most recently tested 2020-10-28 with the following git release: 22 | 23 | ``` 24 | % git --version 25 | git version 2.21.0 (Apple Git-122) 26 | ``` 27 | 28 | 29 | 30 | ## Install Homebrew 31 | 32 | Homebrew's site gives a shell command to download and install it 33 | https://brew.sh/ 34 | 35 | To update both the installed homebrew version and its list of formulae: 36 | 37 | ``` 38 | % brew update 39 | ``` 40 | 41 | To upgrade software installed via brew: 42 | 43 | ``` 44 | $ brew upgrade 45 | ``` 46 | 47 | Homebrew has a search page you can use to look up formula names: http://formulae.brew.sh/ 48 | 49 | Most recently tested 2020-10-28 with the following Homebrew release: 50 | 51 | ``` 52 | % brew --version 53 | Homebrew 2.5.7 54 | Homebrew/homebrew-core (git revision 8a3edd; last commit 2020-10-28) 55 | Homebrew/homebrew-cask (git revision 98c84; last commit 2020-10-28) 56 | ``` 57 | 58 | That last line about "homebrew-cask" refers to a subcommand 'cask' that can manage the types of 59 | installs mac users ordinarily do manually - the "drag to the applications folder" type and the "run 60 | an installer" type. 61 | 62 | We'll use both "brew" and "brew cask" install methods in the steps below. 63 | 64 | 65 | 66 | ## Install Virtualbox 67 | 68 | This one may fail on the first attempt with a prompt to allow software signed by Oracle. After doing 69 | that, the second attempt should succeed. 70 | 71 | ``` 72 | $ brew cask install virtualbox 73 | ``` 74 | 75 | Most recently tested 2020-10-28 with the following Virtualbox release: 76 | 77 | ``` 78 | % VBoxManage --version 79 | 6.0.15r135660 80 | ``` 81 | 82 | 83 | 84 | ## Install Vagrant 85 | 86 | ``` 87 | $ brew cask install vagrant 88 | ``` 89 | 90 | Most recently tested 2020-10-28 with the following Vagrant release: 91 | 92 | ``` 93 | % vagrant --version 94 | Vagrant 2.2.7 95 | ``` 96 | 97 | 98 | 99 | ## Install GnuPG 2.x (2.11.18 or greater) 100 | 101 | ``` 102 | $ brew install gnupg 103 | ``` 104 | 105 | Most recently tested 2020-10-28 with the following GnuPG release: 106 | 107 | ``` 108 | % gpg --version 109 | gpg (GnuPG) 2.2.20 110 | libgcrypt 1.8.5 111 | [...] 112 | ``` 113 | 114 | 115 | 116 | ## Install Python 3.x 117 | 118 | As of this writing, python 3.7.3 is installed by default in macOS, which should work fine. You can 119 | optionally install the 'python' homebrew package to get a later version. 120 | 121 | ``` 122 | $ brew install python 123 | ``` 124 | 125 | Note that to run python 3.x you need to use the name `python3`; running `python` will run python 126 | 2.x. 127 | 128 | Most recently tested 2020-10-28 with the following Python release: 129 | 130 | ``` 131 | % python3 --version 132 | Python 3.8.2 133 | ``` 134 | 135 | 136 | 137 | # Install direnv (Optional/Recommended) 138 | 139 | This tool sets and unsets environment variables as you change directories in a shell session, 140 | providing a convenient facility for setting up project-specific configuration. 141 | 142 | ``` 143 | brew install direnv 144 | ``` 145 | 146 | To activate direnv when starting bash (the default shell on macOS), add the following line to the 147 | end of `~/.profile`: 148 | 149 | ``` 150 | eval "$(direnv hook bash)" 151 | ``` 152 | 153 | direnv works by incorporating a call to `_direnv_hook` in the `PROMPT_COMMAND` shell variable. You 154 | can check that this was done by starting a new bash session and checking whether that value is 155 | present: 156 | 157 | ``` 158 | $ echo $PROMPT_COMMAND 159 | _direnv_hook;[...] 160 | ``` 161 | 162 | direnv also supports several other shells -- zsh, fish, tcsh, and elvish as of this writing. Its 163 | website includes instructions for enabling each of the shells it supports. 164 | 165 | Most recently tested 2020-10-28 with the following direnv release: 166 | 167 | ``` 168 | % direnv --version 169 | 2.23.1 170 | ``` 171 | -------------------------------------------------------------------------------- /docs/gpg_keys.md: -------------------------------------------------------------------------------- 1 | Notes on updating or revoking GPG keys 2 | 3 | First a note about terminology. A potentially confusing thing with GPG is the overloaded meanings of terms. It is probably helpful to state up front that this system operates on collections of associated identities and credentials. Often an entire such collection is referred to as a 'key' or a 'keypair', while keys inside the collection are also called keys and keypairs. Here I'll try and say "key bundle" when referring to the whole collection, but you probably won't see that term used elsewhere in the worlds of GPG and PGP. 4 | 5 | A key bundle consists of: 6 | - A 'master' or 'primary' keypair (private + public key) 7 | - Zero or more 'subordinate keypairs', often shortened to 'subordinate keys' or 'subkeys'. 8 | - Zero or more 'user ids' (strings of the form "FirstName LastName (comment) ") 9 | - Zero or more key signatures 10 | - For example, a signature by the private primary key of the public primary key 11 | ...or cross-signatures in both directions between the primary keypair and subordinate keypairs 12 | ...or signatures on the user ids by the primary private key 13 | - Zero or more 'revocation certificates', revoking any of the signatures mentioned above 14 | 15 | When publishing or retrieving something to or from the key server network, these key bundles are the units you are working with. Publishing a key bundle is a create/update operation. In the 'update' case the key bundle gets merged with older copies of that key bundle. A merge operation will combine fields from the key bundles being merged. 16 | 17 | It is possible to delete pieces from a key bundle, but that is probably not what you want, since they might well reappear after the updated key is published and merged throughout the key server network. Instead, add a revocation for the thing you might have wanted to remove. 18 | 19 | 20 | - Publish a key bundle to the key server network 21 | gpg --send-keys (fingerprint) 22 | - Then we want clients to get the updated key bundle 23 | - For clients using gpg directly that might be done with: 24 | gpg --refresh-keys 25 | - For clients using gpg via apt that might be done with: 26 | sudo apt-key adv --refresh-keys 27 | 28 | - If a subkey expires 29 | - Use master key to generate a new subkey 30 | gpg --edit-key (fingerprint) gives a prompt; then use 'addkey' subcommand at prompt 31 | - subkey is added to key bundle 32 | - See 'Publish a key bundle to the key server network' above 33 | 34 | - If a subkey is compromised 35 | - Use master key to generate a revocation certificate for that subkey 36 | gpg --edit-key (fingerprint) gives a prompt; then use 'revkey' subcommand at prompt 37 | - revocation certificate is added to key bundle 38 | - See 'Publish a key bundle to the key server network' above 39 | 40 | - Before master/primary key expires 41 | - Although GPG key bundles have expiration times, these can be extended using the private master key 42 | - It is probably helpful to know something about what's happening under the covers. The expiration time is associated with the 'self-signature' (of the public primary key by the private primary key). By adding a new self-signature to the key bundle with a later expiration date, clients with the updated bundle should honor the date on the newer self-signature rather than the older one. 43 | - This update can be performed with the following command: 44 | gpg --quick-set-expire (fingerprint) (new_expiration_time) 45 | - This should add that new self-signature described above to the bundle 46 | - See 'Publish a key bundle to the key server network' above 47 | 48 | - If master/primary key expires 49 | - Clients will now get validation errors since the expiration date is in the past. But the update process should be the same as 'before master/primary key expires'. Follow the same steps described there. 50 | 51 | - If master/primary key is compromised 52 | - Use master/primary key to generate a revocation certificate for itself 53 | gpg --generate-revocation (fingerprint) > revocation.cert 54 | - The revocation certificate is detached from the key bundle, in its own file. This step can be done ahead of time if desired, and the revocation certificate file kept in a safe place. 55 | - To add the revocation certificate to the key bundle: 56 | gpg --import revocation.cert 57 | - Your local gpg instance now considers the primary key revoked 58 | - See 'Publish a key bundle to the key server network' above to propagate the revocation to the rest of the world 59 | -------------------------------------------------------------------------------- /forward_gpg_agent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | GPG_SOCK=$(echo "$GPG_AGENT_INFO" | cut -d: -f1) 4 | if [ -z "$GPG_SOCK" ] ; then 5 | echo "No GPG agent configured - this won't work out." >&2 6 | exit 1 7 | fi 8 | 9 | vagrant ssh axe-build -- rm -f /home/vagrant/.gnupg/S.gpg-agent 10 | vagrant ssh axe-build -- -t \ 11 | -R /home/vagrant/.gnupg/S.gpg-agent:$GPG_SOCK \ 12 | -o StreamLocalBindUnlink=yes \ 13 | -o ExitOnForwardFailure=yes 14 | -------------------------------------------------------------------------------- /gitian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Apply the AXE Gitian builder role. 3 | become: yes 4 | hosts: localhost:axe-build 5 | vars: 6 | axe_git_repo_url: "{{ lookup('env','AXE_GIT_REPO_URL') }}" 7 | axe_version: "{{ lookup('env','AXE_VERSION') }}" 8 | git_name: "{{ lookup('env','GIT_NAME') }}" 9 | git_email: "{{ lookup('env','GIT_EMAIL') }}" 10 | gpg_key_name: "{{ lookup('env','GPG_KEY_NAME') }}" 11 | gpg_key_id: "{{ lookup('env','GPG_KEY_ID') }}" 12 | roles: 13 | - role: common 14 | tags: common 15 | - role: gitian 16 | tags: gitian 17 | -------------------------------------------------------------------------------- /local/README.md: -------------------------------------------------------------------------------- 1 | local/ 2 | ====== 3 | 4 | This directory is intended for content that is local to your work area, and 5 | not intended to be tracked by version control. 6 | 7 | This file is here to make git track the existence of this directory (git doesn't 8 | track empty directories). 9 | -------------------------------------------------------------------------------- /requirements-pip.lock: -------------------------------------------------------------------------------- 1 | # Primary Dependencies 2 | # (Packages we actually decided to include) 3 | ansible==2.10.1 4 | # Secondary Dependencies 5 | # (pulled in by one or more of the above dependencies) 6 | ansible-base==2.10.2 7 | cffi==1.14.3 8 | cryptography==3.2.1 9 | Jinja2==2.11.2 10 | MarkupSafe==1.1.1 11 | packaging==20.4 12 | pycparser==2.20 13 | pyparsing==2.4.7 14 | PyYAML==5.3.1 15 | six==1.15.0 -------------------------------------------------------------------------------- /roles/common/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | axe_swapfile_size: 2G 3 | axe_vm_swappiness: 1 4 | axe_common_packages: 5 | - apt-show-versions 6 | - apt-transport-https 7 | - curl 8 | - git-core 9 | - haveged 10 | - htop 11 | - ntp 12 | - ntpdate 13 | - python-pip 14 | - rsync 15 | - screen 16 | - sudo 17 | - tmux 18 | - tree 19 | - vim 20 | -------------------------------------------------------------------------------- /roles/common/files/02periodic: -------------------------------------------------------------------------------- 1 | APT::Periodic::Enable "1"; 2 | APT::Periodic::Update-Package-Lists "1"; 3 | APT::Periodic::Download-Upgradeable-Packages "1"; 4 | APT::Periodic::Unattended-Upgrade "1"; 5 | APT::Periodic::AutocleanInterval "7"; 6 | -------------------------------------------------------------------------------- /roles/common/files/50unattended-upgrades: -------------------------------------------------------------------------------- 1 | Unattended-Upgrade::Origins-Pattern { 2 | "o=Debian,n=stretch-updates"; 3 | "o=Debian,n=stretch,l=Debian-Security"; 4 | }; 5 | Unattended-Upgrade::Remove-Unused-Dependencies "true"; 6 | Unattended-Upgrade::Automatic-Reboot "false"; 7 | -------------------------------------------------------------------------------- /roles/common/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: update timezone 3 | command: dpkg-reconfigure --frontend noninteractive tzdata 4 | -------------------------------------------------------------------------------- /roles/common/tasks/add_github_ssh_hostkey.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Look up GitHub SSH host key. 3 | local_action: command ssh-keyscan -t rsa github.com 4 | register: github_ssh_keyscan_result 5 | changed_when: false 6 | check_mode: no 7 | run_once: yes 8 | become: no 9 | 10 | - name: Ensure github.com is a known host. 11 | known_hosts: 12 | path: /etc/ssh/ssh_known_hosts 13 | name: github.com 14 | key: "{{ github_ssh_keyscan_result.stdout }}" 15 | -------------------------------------------------------------------------------- /roles/common/tasks/auto_upgrades.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Copy unattended-upgrades configuration. 3 | copy: 4 | dest: /etc/apt/apt.conf.d/ 5 | src: "{{ item }}" 6 | mode: "0640" 7 | owner: root 8 | group: root 9 | with_items: 10 | - 02periodic 11 | - 50unattended-upgrades 12 | 13 | - name: Enable automatic updates in unattended-upgrades package config. 14 | shell: echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections 15 | -------------------------------------------------------------------------------- /roles/common/tasks/hostname.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Set hostname. 3 | hostname: 4 | name: "axe-build" 5 | 6 | - name: Build /etc/hosts file. 7 | lineinfile: 8 | dest: /etc/hosts 9 | regexp: '^127.0.1.1' 10 | line: "127.0.1.1 axe-build" 11 | state: present 12 | -------------------------------------------------------------------------------- /roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: repartition.yml 3 | - include_tasks: update_everything.yml 4 | - include_tasks: packages.yml 5 | - include_tasks: make_swap.yml 6 | - include_tasks: add_github_ssh_hostkey.yml 7 | - include_tasks: hostname.yml 8 | - include_tasks: motd.yml 9 | - include_tasks: vim.yml 10 | - include_tasks: auto_upgrades.yml 11 | -------------------------------------------------------------------------------- /roles/common/tasks/make_swap.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check whether swap file already exists. 3 | stat: 4 | path: /swapfile 5 | register: existing_swapfile_result 6 | 7 | - name: Allocate swapfile. 8 | command: "fallocate -l {{ axe_swapfile_size }} /swapfile" 9 | when: not existing_swapfile_result.stat.exists 10 | 11 | - name: Set permissions of swapfile. 12 | file: 13 | path: /swapfile 14 | owner: root 15 | group: root 16 | mode: "0600" 17 | state: touch 18 | 19 | - name: Set up the swapfile. 20 | command: mkswap /swapfile 21 | when: not existing_swapfile_result.stat.exists 22 | 23 | - name: Enable the swapfile. 24 | command: swapon /swapfile 25 | when: not existing_swapfile_result.stat.exists 26 | 27 | - name: Make the swapfile persistent. 28 | lineinfile: 29 | dest: /etc/fstab 30 | regexp: "^/swapfile" 31 | line: "/swapfile none swap sw 0 0" 32 | 33 | - name: Set vm.swappiness in sysctl. 34 | sysctl: 35 | name: vm.swappiness 36 | value: "{{ axe_vm_swappiness }}" 37 | state: present 38 | -------------------------------------------------------------------------------- /roles/common/tasks/motd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get the current kernel version string. 3 | command: uname -a 4 | register: kernel_version_string 5 | 6 | - name: Install motd (message of the day). 7 | template: 8 | src: motd.j2 9 | dest: /etc/motd 10 | owner: root 11 | group: root 12 | mode: "0644" 13 | -------------------------------------------------------------------------------- /roles/common/tasks/packages.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install some common packages. 3 | apt: 4 | name: '{{ axe_common_packages }}' 5 | state: present 6 | update_cache: yes 7 | cache_valid_time: 3600 8 | -------------------------------------------------------------------------------- /roles/common/tasks/repartition.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Make sure parted is installed 3 | apt: 4 | name: parted 5 | state: present 6 | update_cache: yes 7 | 8 | - name: Turn off all swap areas 9 | command: swapoff -a 10 | become: yes 11 | 12 | - name: Remove swap partition from /etc/fstab 13 | mount: 14 | path: none 15 | fstype: swap 16 | opts: sw 17 | state: absent 18 | 19 | - name: Remove partition number 5 20 | parted: 21 | device: /dev/sda 22 | number: 5 23 | state: absent 24 | 25 | - name: Remove partition number 2 26 | parted: 27 | device: /dev/sda 28 | number: 2 29 | state: absent 30 | register: rm_part_2_sda_info 31 | 32 | - name: Resize partition 1 to reach end of disk if it does not already 33 | command: parted ---pretend-input-tty /dev/sda unit % resizepart 1 yes 100 34 | become: yes 35 | when: rm_part_2_sda_info['disk']['size'] != rm_part_2_sda_info['partitions'][0]['end'] 36 | register: parted_resize 37 | 38 | - name: Resize filesystem on /dev/sda1 to fill the available space on the partition 39 | filesystem: 40 | dev: /dev/sda1 41 | fstype: ext4 42 | resizefs: true 43 | -------------------------------------------------------------------------------- /roles/common/tasks/update_everything.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check if sudo is installed. 3 | command: dpkg-query -l sudo 4 | register: sudo_installed_result 5 | # dpkg returns 1 if package not found, 6 | # so disable the scary red text by setting no-fail mode. 7 | # The output from the command is checked in the next task. 8 | failed_when: false 9 | changed_when: false 10 | # Necessary to support --check mode 11 | check_mode: no 12 | 13 | - name: Install sudo. 14 | apt: 15 | name: sudo 16 | state: present 17 | update_cache: yes 18 | cache_valid_time: 3600 19 | when: "'no packages found' in sudo_installed_result.stderr" 20 | 21 | - name: Update apt cache. 22 | apt: 23 | update_cache: yes 24 | cache_valid_time: 3600 25 | 26 | - name: Install aptitude. 27 | apt: 28 | name: aptitude 29 | state: present 30 | update_cache: yes 31 | cache_valid_time: 3600 32 | 33 | - name: Perform aptitude safe-upgrade. 34 | apt: 35 | upgrade: safe 36 | update_cache: yes 37 | cache_valid_time: 3600 38 | tags: apt 39 | 40 | - name: Remove unneeded packages. 41 | apt: 42 | autoremove: yes 43 | tags: apt 44 | -------------------------------------------------------------------------------- /roles/common/tasks/vim.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Set default EDITOR to vim. 3 | command: update-alternatives --set editor /usr/bin/vim.basic 4 | 5 | - name: Enable syntax highlighting. 6 | lineinfile: 7 | dest: /etc/vim/vimrc 8 | regexp: "^\"syntax on" 9 | line: "syntax on" 10 | 11 | - name: Enable filetype detection. 12 | lineinfile: 13 | dest: /etc/vim/vimrc 14 | regexp: "^\"filetype on" 15 | line: "filetype on" 16 | 17 | - name: Disable swap files. 18 | lineinfile: 19 | dest: /etc/vim/vimrc 20 | regexp: "^\"set noswapfile" 21 | line: "set noswapfile" 22 | -------------------------------------------------------------------------------- /roles/common/templates/log-core-dump.j2: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Handler for processing coredumps. Should be invoked only by system 3 | # via the `kernel.core_pattern` in pipe mode, not run interactively. 4 | # It assumes that filename, executable, and uid will be passed as args. 5 | 6 | 7 | coredump_filename=$1 8 | coredump_executable=$2 9 | coredump_uid=$3 10 | 11 | # Ensure we're running as root. 12 | if [ $EUID -ne 0 ]; then 13 | echo "Only root may run this script." 1>&2 14 | exit 1 15 | fi 16 | 17 | # Ensure script is running as part of pipe, receiving stdin. 18 | # If script is run from an interactive terminal, exit. 19 | if [ -t 0 ]; then 20 | echo "No stdin pipe detected, exiting." 1>&2 21 | exit 1 22 | fi 23 | 24 | # Check for required arguments for logging and dumping core. 25 | if [ -z $coredump_filename ] || [ -z $coredump_executable ] || [ -z $coredump_uid ]; then 26 | echo "Missing required arguments for handling core dump." 1>&2 27 | exit 1 28 | fi 29 | 30 | # Log coredump event to syslog. 31 | /usr/bin/logger "Core dump detected: ${coredump_executable} owned by uid ${coredump_uid}" 32 | 33 | # Ensure files are 0600 root:root. 34 | umask 277 35 | 36 | # Redirect core dump content from stdin to target file. 37 | cat - > "{{ coredumps_directory }}/${coredump_filename}" 38 | -------------------------------------------------------------------------------- /roles/common/templates/motd.j2: -------------------------------------------------------------------------------- 1 | {{ kernel_version_string.stdout }} 2 | 3 | █████╗ ██╗ ██╗ ███████╗ 4 | ██╔══██╗ ╚██╗██╔╝ ██╔════╝ 5 | ███████║ ╚███╔╝ █████╗ 6 | ██╔══██║ ██╔██╗ ██╔══╝ 7 | ██║ ██║ ██╔╝ ██╗ ███████╗ 8 | ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ 9 | 10 | Hostname: {{ ansible_fqdn }} 11 | IP address: {{ ansible_default_ipv4.address }} 12 | -------------------------------------------------------------------------------- /roles/gitian/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | gitian_user: vagrant 3 | download_directory: /tmp/gitian 4 | vm_builder_name: 'vm-builder-0.12.4+bzr494' 5 | vm_builder_url: 'http://archive.ubuntu.com/ubuntu/pool/universe/v/vm-builder/vm-builder_0.12.4+bzr494.orig.tar.gz' 6 | gitian_builder_url: https://github.com/devrandom/gitian-builder 7 | gitian_builder_version: master 8 | axe_git_repo_url: https://github.com/AXErunners/axe 9 | axe_gitian_sigs_repo: https://github.com/AXErunners/gitian.sigs 10 | axe_version: master 11 | gitian_host_ip: 10.0.2.15 12 | lxc_guest_ip: 10.0.3.5 13 | axe_developer_pubkeys: 14 | - name: charlesrocket 15 | id: 5AC27140 16 | - name: ddude1 17 | id: B306325A 18 | - name: sparkuss 19 | id: 4033F6D8 20 | -------------------------------------------------------------------------------- /roles/gitian/files/explode_yaml_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import argparse 5 | import os 6 | import ruamel.yaml 7 | 8 | from ruamel.yaml.scalarstring import DoubleQuotedScalarString 9 | 10 | # For a command like this... 11 | # 12 | # explode_yaml_file.py axe/contrib/gitian-descriptors/gitian-linux.yml suites output_dir 13 | # 14 | # ...with a gitian-linux.yml file like this... 15 | # 16 | # --- 17 | # distro: "debian" 18 | # suites: 19 | # - "jessie" 20 | # - "stretch" 21 | # architectures: 22 | # - "amd64" 23 | # 24 | # ...will write out a structure like this: 25 | # 26 | # output_dir/ 27 | # ├─ jessie/ 28 | # │ └─ gitian-linux.yml content: 29 | # │ --- 30 | # │ distro: "debian" 31 | # │ suites: 32 | # │ - "jessie" 33 | # │ architectures: 34 | # │ - "amd64" 35 | # │ 36 | # └─ stretch 37 | # └─ gitian-linux.yml content: 38 | # --- 39 | # distro: "debian" 40 | # suites: 41 | # - "stretch" 42 | # architectures: 43 | # - "amd64" 44 | # 45 | # This approach is working around a limitation of gitian-builder: when 46 | # passed a descriptor file with more than one entry in 'suites', it 47 | # overwrites products of earlier builds with products of later builds. 48 | # We 'explode' our descriptor file into potentially many single-suite 49 | # descriptor files which we then pass to gitian-builder one at a time. 50 | 51 | 52 | parser = argparse.ArgumentParser(description='YAML file exploder') 53 | 54 | parser.add_argument('input_file_path', 55 | type=str, 56 | help='Path to the input file') 57 | 58 | parser.add_argument('key_to_explode', 59 | type=str, 60 | help='The key in the input file to explode (should be a sequence)') 61 | 62 | parser.add_argument('output_dir_path', 63 | type=str, 64 | help='Path to the output directory') 65 | 66 | args = parser.parse_args() 67 | 68 | yaml = ruamel.yaml.YAML() 69 | yaml.preserve_quotes = True 70 | 71 | input_file_path = args.input_file_path 72 | output_dir_path = args.output_dir_path 73 | 74 | file_name = os.path.basename(input_file_path) 75 | 76 | 77 | with open(input_file_path) as fp: 78 | data = yaml.load(fp) 79 | 80 | sequence = data[args.key_to_explode] 81 | 82 | for item in sequence: 83 | print item 84 | item_dir_path = os.path.join(output_dir_path, item) 85 | 86 | if not os.path.exists(item_dir_path): 87 | os.makedirs(item_dir_path) 88 | 89 | data[args.key_to_explode] = [DoubleQuotedScalarString(item)] 90 | 91 | output_file_path = os.path.join(item_dir_path, file_name) 92 | with open(output_file_path, 'w') as fp: 93 | yaml.dump(data, fp) 94 | -------------------------------------------------------------------------------- /roles/gitian/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Kevin Gallagher (@ageis) Kent Sommer (@kentsommer) Kirill Orlov (@charlesrocket) and Jonathan Leto (@leto) 4 | description: Sets up a deterministic Gitian builder VM for AXE. 5 | company: AXE 6 | galaxy_tags: [] 7 | license: GPLv2 8 | min_ansible_version: 2.1.2 9 | platforms: 10 | - name: Debian 11 | versions: 12 | - jessie 13 | categories: 14 | - system 15 | dependencies: [] 16 | -------------------------------------------------------------------------------- /roles/gitian/tasks/gpg.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check that the secret key exists. 3 | local_action: "shell gpg --list-secret-keys --with-colons | grep {{ gpg_key_id }}" 4 | become: no 5 | ignore_errors: true 6 | register: gpg_list_keys_result 7 | 8 | - name: Export the GPG private key from the local keyring. 9 | local_action: "command gpg --armor --export-secret-key {{ gpg_key_id }}" 10 | become: no 11 | register: gpg_private_key 12 | changed_when: false 13 | when: gpg_list_keys_result.stdout != '' 14 | no_log: True 15 | 16 | - name: Write the private key to a temp file. 17 | copy: 18 | dest: "/tmp/{{ gpg_key_id }}.sec" 19 | content: "{{ gpg_private_key.stdout }}" 20 | owner: "{{ gitian_user }}" 21 | group: "{{ gitian_user }}" 22 | mode: "0400" 23 | when: gpg_list_keys_result.stdout != '' 24 | no_log: True 25 | 26 | - name: Make GnuPG home directory. 27 | file: 28 | path: "/home/{{ gitian_user }}/.gnupg" 29 | state: directory 30 | mode: "0700" 31 | owner: "{{ gitian_user }}" 32 | group: "{{ gitian_user }}" 33 | 34 | - name: Write GnuPG configuration. 35 | template: 36 | src: gpg.conf 37 | dest: "/home/{{ gitian_user }}/.gnupg/gpg.conf" 38 | mode: "0600" 39 | owner: "{{ gitian_user }}" 40 | group: "{{ gitian_user }}" 41 | 42 | - name: Import the GPG private key to the Vagrant user. 43 | command: "gpg --batch --import /tmp/{{ gpg_key_id }}.sec" 44 | become_user: "{{ gitian_user }}" 45 | when: gpg_list_keys_result.stdout != '' and gpg_private_key.stdout is defined 46 | no_log: True 47 | register: gpg_output 48 | changed_when: "'secret key imported' in gpg_output.stderr" 49 | failed_when: gpg_output.rc != 0 and 'already in secret keyring' not in gpg_output.stderr 50 | 51 | - name: Clean up secret key file in /tmp. 52 | file: 53 | path: "/tmp/{{ gpg_key_id }}.sec" 54 | state: absent 55 | -------------------------------------------------------------------------------- /roles/gitian/tasks/keys.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Download AXE developer public keys from website. 3 | become: yes 4 | get_url: 5 | url: "https://raw.githubusercontent.com/AXErunners/gitian.sigs/master/{{ item.name }}.asc" 6 | dest: "/tmp/{{ item.id }}.asc" 7 | owner: "{{ gitian_user }}" 8 | group: "{{ gitian_user }}" 9 | mode: "0644" 10 | with_items: "{{ axe_developer_pubkeys }}" 11 | 12 | - name: Import AXE developer public keys. 13 | command: "gpg --import /tmp/{{ item.id }}.asc" 14 | become_user: "{{ gitian_user }}" 15 | with_items: "{{ axe_developer_pubkeys }}" 16 | 17 | - name: Set AXE developer public keys to ultimately trusted. 18 | shell: > 19 | gpg --list-keys --with-colons --with-fingerprint `gpg --list-keys 20 | --with-colons | grep "pub:f:.*:-:" | 21 | sed -r -e 's/pub:f:[0-9]+:[0-9]+:([A-F0-9]+):.*/0x\1/'` | grep "^fpr:" | 22 | sed -r -e 's/fpr:::::::::([0-9A-F]+):/\1:6:/' | gpg --import-ownertrust 23 | become_user: "{{ gitian_user }}" 24 | args: 25 | executable: /bin/bash 26 | -------------------------------------------------------------------------------- /roles/gitian/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check that custom git variables are defined. 3 | assert: 4 | that: 5 | - "gpg_key_name is defined" 6 | - "gpg_key_name != ''" 7 | - "git_name is defined" 8 | - "git_name != ''" 9 | - "git_email is defined" 10 | - "git_email != ''" 11 | msg: Please set your gpg_key_name, git_name and git_email in gitian.yml. 12 | 13 | - name: Install Gitian dependencies. 14 | apt: 15 | name: 16 | - apt-cacher-ng 17 | - bridge-utils 18 | - ca-certificates 19 | - curl 20 | - debootstrap 21 | - git-core 22 | - gnupg2 23 | - kpartx 24 | - lintian 25 | - lxc 26 | - make 27 | - python-cheetah 28 | - qemu-utils 29 | - ruby 30 | - sudo 31 | state: present 32 | update_cache: yes 33 | 34 | - name: Add Docker GPG apt Key 35 | apt_key: 36 | url: https://download.docker.com/linux/debian/gpg 37 | state: present 38 | 39 | - name: Add Docker Repository 40 | apt_repository: 41 | repo: deb https://download.docker.com/linux/debian stretch stable 42 | state: present 43 | update_cache: yes 44 | 45 | - name: Install ruamel.yaml 46 | pip: 47 | name: "ruamel.yaml" 48 | 49 | - name: Set up the Gitian build user with sudo. 50 | user: 51 | name: "{{ gitian_user }}" 52 | shell: /bin/bash 53 | groups: sudo 54 | state: present 55 | 56 | - name: Install /etc/rc.local. 57 | template: 58 | src: rc.local 59 | dest: /etc/rc.local 60 | owner: root 61 | group: root 62 | mode: "0755" 63 | 64 | - name: Enable IP forwarding, etc. 65 | sysctl: 66 | name: "{{ item }}" 67 | value: 1 68 | sysctl_set: yes 69 | state: present 70 | reload: yes 71 | with_items: 72 | - net.ipv4.ip_forward 73 | - kernel.unprivileged_userns_clone 74 | 75 | - name: Enable cgroup clone_children. 76 | command: "echo 1 > /sys/fs/cgroup/cpuset/cgroup.clone_children" 77 | 78 | - name: Add cgroup fs for LXC. 79 | lineinfile: 80 | dest: /etc/fstab 81 | regexp: '^cgroup' 82 | line: 'cgroup /sys/fs/cgroup cgroup defaults 0 0' 83 | state: present 84 | 85 | - name: Install profile with environment variables. 86 | template: 87 | src: profile 88 | dest: "/home/{{ gitian_user }}/.profile" 89 | owner: "{{ gitian_user }}" 90 | group: "{{ gitian_user }}" 91 | mode: "0644" 92 | 93 | - name: Install sudoers file for LXC. 94 | template: 95 | src: gitian-lxc 96 | dest: /etc/sudoers.d/gitian-lxc 97 | owner: root 98 | group: root 99 | mode: "0644" 100 | 101 | - name: Create directory for downloaded files. 102 | file: 103 | state: directory 104 | dest: "{{ download_directory }}" 105 | mode: "0755" 106 | 107 | - name: Download and extract VM builder source code. 108 | unarchive: 109 | src: "{{ vm_builder_url }}" 110 | dest: "{{ download_directory }}" 111 | remote_src: yes 112 | 113 | - name: Install VM builder Python module. 114 | command: "python setup.py install" 115 | args: 116 | chdir: "/tmp/gitian/{{ vm_builder_name }}" 117 | 118 | - name: Install lxc-net configuration. 119 | template: 120 | src: lxc-net 121 | dest: /etc/default/lxc-net 122 | owner: root 123 | group: root 124 | mode: "0644" 125 | 126 | - name: Clone git repository for Gitian builder. 127 | git: 128 | repo: "{{ gitian_builder_url }}" 129 | dest: "/home/{{ gitian_user }}/gitian-builder" 130 | version: "{{ gitian_builder_version }}" 131 | force: yes 132 | become_user: "{{ gitian_user }}" 133 | 134 | - include_tasks: keys.yml 135 | tags: keys 136 | 137 | - name: Clone git repository for AXE. 138 | git: 139 | repo: "{{ axe_git_repo_url }}" 140 | dest: "/home/{{ gitian_user }}/axe" 141 | version: "{{ axe_version }}" 142 | force: yes 143 | become_user: "{{ gitian_user }}" 144 | 145 | - name: Clone git repository for Gitian signatures. 146 | git: 147 | repo: "{{ axe_gitian_sigs_repo }}" 148 | dest: "/home/{{ gitian_user }}/gitian.sigs" 149 | version: master 150 | force: yes 151 | become_user: "{{ gitian_user }}" 152 | 153 | - name: Reboot. 154 | shell: sleep 3 && shutdown -r now "Rebooting..." 155 | async: 1 156 | poll: 0 157 | ignore_errors: true 158 | become: yes 159 | 160 | - name: Figure out the Vagrant VM's SSH port number. 161 | local_action: "shell vagrant ssh-config axe-build | grep Port | awk {'print $2'}" 162 | register: vagrant_ssh_port 163 | become: no 164 | 165 | - name: Wait for virtual machine to come back. 166 | local_action: wait_for 167 | host={{ ansible_host | default('localhost') }} 168 | port={{ vagrant_ssh_port.stdout | int }} 169 | delay=30 170 | state=started 171 | become: no 172 | 173 | - name: Wait extra time for VM to come back up. 174 | pause: 175 | seconds: 10 176 | 177 | - name: Set Git username. 178 | command: "git config --global user.name \"{{ git_name }}\"" 179 | become_user: "{{ gitian_user }}" 180 | 181 | - name: Set Git email address. 182 | command: "git config --global user.email '{{ git_email }}'" 183 | become_user: "{{ gitian_user }}" 184 | 185 | - name: Create bin directory under gitian_user home directory 186 | file: 187 | state: directory 188 | dest: "/home/{{ gitian_user }}/bin" 189 | mode: "0755" 190 | 191 | - name: Copy explode_yaml_file.py 192 | copy: 193 | src: explode_yaml_file.py 194 | dest: "/home/{{ gitian_user }}/bin/explode_yaml_file.py" 195 | owner: "{{ gitian_user }}" 196 | group: "{{ gitian_user }}" 197 | mode: "0755" 198 | 199 | - name: Copy Gitian build script. 200 | template: 201 | src: gitian-build.py 202 | dest: "/home/{{ gitian_user }}/gitian-build.py" 203 | owner: "{{ gitian_user }}" 204 | group: "{{ gitian_user }}" 205 | mode: "0755" 206 | tags: script 207 | 208 | - name: Clean the apt cache to free up space. 209 | apt: 210 | autoclean: yes 211 | 212 | - include_tasks: gpg.yml 213 | tags: gpg 214 | when: gpg_key_id is defined and gpg_key_id != '' 215 | 216 | - name: Ensure group "docker" exists 217 | group: 218 | name: docker 219 | state: present 220 | system: yes 221 | 222 | - name: Execute Docker without sudo 223 | shell: sh -c "sudo usermod -aG docker vagrant" 224 | become: yes 225 | become_user: vagrant 226 | become_method: sudo 227 | 228 | - name: Prepare input directory for Apple SDK 229 | file: 230 | path: "gitian-builder/inputs" 231 | state: directory 232 | recurse: yes 233 | owner: vagrant 234 | 235 | - name: Copy Apple SDK 236 | copy: 237 | src: MacOSX10.11.sdk.tar.gz 238 | dest: gitian-builder/inputs/MacOSX10.11.sdk.tar.gz 239 | owner: vagrant 240 | ignore_errors: yes 241 | 242 | - name: Display help message. 243 | debug: 244 | msg: >- 245 | Finished bootstrapping the Gitian host VM! 246 | To enter the environment, run `vagrant ssh axe-build` 247 | and then use `./gitian-build.py` to kick off a build. 248 | -------------------------------------------------------------------------------- /roles/gitian/templates/gitian-build.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import os 5 | import subprocess 6 | import sys 7 | 8 | def setup(): 9 | global args, workdir 10 | programs = ['ruby', 'git', 'make', 'wget'] 11 | if args.lxc: 12 | programs += ['apt-cacher-ng', 'lxc', 'debootstrap'] 13 | elif args.kvm: 14 | programs += ['apt-cacher-ng', 'python-vm-builder', 'qemu-kvm', 'qemu-utils'] 15 | elif args.docker and not os.path.isfile('/lib/systemd/system/docker.service'): 16 | dockers = ['docker.io', 'docker-ce'] 17 | for i in dockers: 18 | return_code = subprocess.call(['sudo', 'apt-get', 'install', '-qq', i]) 19 | if return_code == 0: 20 | break 21 | if return_code != 0: 22 | print('Cannot find any way to install Docker', file=sys.stderr) 23 | exit(1) 24 | subprocess.check_call(['sudo', 'apt-get', 'install', '-qq'] + programs) 25 | if not os.path.isdir('gitian.sigs'): 26 | subprocess.check_call(['git', 'clone', 'https://github.com/axerunners/gitian.sigs.git']) 27 | if not os.path.isdir('axe-detached-sigs'): 28 | subprocess.check_call(['git', 'clone', 'https://github.com/axerunners/axe-detached-sigs.git']) 29 | if not os.path.isdir('gitian-builder'): 30 | subprocess.check_call(['git', 'clone', 'https://github.com/devrandom/gitian-builder.git']) 31 | if not os.path.isdir('axe'): 32 | subprocess.check_call(['git', 'clone', 'https://github.com/axerunners/axe.git']) 33 | os.chdir('gitian-builder') 34 | make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64'] 35 | if args.docker: 36 | make_image_prog += ['--docker'] 37 | elif args.lxc: 38 | make_image_prog += ['--lxc'] 39 | subprocess.check_call(make_image_prog) 40 | os.chdir(workdir) 41 | if args.is_bionic and not args.kvm and not args.docker: 42 | subprocess.check_call(['sudo', 'sed', '-i', 's/lxcbr0/br0/', '/etc/default/lxc-net']) 43 | print('Reboot is required') 44 | exit(0) 45 | 46 | def build(): 47 | global args, workdir 48 | 49 | os.makedirs('axecore-binaries/' + args.version, exist_ok=True) 50 | print('\nBuilding Dependencies\n') 51 | os.chdir('gitian-builder') 52 | os.makedirs('inputs', exist_ok=True) 53 | 54 | subprocess.check_call(['wget', '-O', 'inputs/osslsigncode-2.0.tar.gz', 'https://github.com/mtrojnar/osslsigncode/archive/2.0.tar.gz']) 55 | subprocess.check_call(["echo '5a60e0a4b3e0b4d655317b2f12a810211c50242138322b16e7e01c6fbb89d92f inputs/osslsigncode-2.0.tar.gz' | sha256sum -c"], shell=True) 56 | subprocess.check_call(['make', '-C', '../axe/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common']) 57 | 58 | if args.linux: 59 | print('\nCompiling ' + args.version + ' Linux') 60 | subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'axe='+args.commit, '--url', 'axe='+args.url, '../axe/contrib/gitian-descriptors/gitian-linux.yml']) 61 | print('\a') 62 | subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-linux', '--destination', '../gitian.sigs/', '../axe/contrib/gitian-descriptors/gitian-linux.yml']) 63 | subprocess.check_call('mv build/out/axecore-*.tar.gz build/out/src/axecore-*.tar.gz ../axecore-binaries/'+args.version, shell=True) 64 | 65 | if args.windows: 66 | print('\nCompiling ' + args.version + ' Windows') 67 | subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'axe='+args.commit, '--url', 'axe='+args.url, '../axe/contrib/gitian-descriptors/gitian-win.yml']) 68 | print('\a') 69 | subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-unsigned', '--destination', '../gitian.sigs/', '../axe/contrib/gitian-descriptors/gitian-win.yml']) 70 | subprocess.check_call('mv build/out/axecore-*-win-unsigned.tar.gz inputs/axecore-win-unsigned.tar.gz', shell=True) 71 | subprocess.check_call('mv build/out/axecore-*.zip build/out/axecore-*.exe ../axecore-binaries/'+args.version, shell=True) 72 | 73 | if args.macos: 74 | print('\nCompiling ' + args.version + ' MacOS') 75 | subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'axe='+args.commit, '--url', 'axe='+args.url, '../axe/contrib/gitian-descriptors/gitian-osx.yml']) 76 | print('\a') 77 | subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-unsigned', '--destination', '../gitian.sigs/', '../axe/contrib/gitian-descriptors/gitian-osx.yml']) 78 | subprocess.check_call('mv build/out/axecore-*-osx-unsigned.tar.gz inputs/axecore-osx-unsigned.tar.gz', shell=True) 79 | subprocess.check_call('mv build/out/axecore-*.tar.gz build/out/axecore-*.dmg ../axecore-binaries/'+args.version, shell=True) 80 | 81 | os.chdir(workdir) 82 | 83 | if args.commit_files: 84 | print('\nCommitting '+args.version+' Unsigned Sigs\n') 85 | os.chdir('gitian.sigs') 86 | subprocess.check_call(['git', 'add', args.version+'-linux/'+args.signer]) 87 | subprocess.check_call(['git', 'add', args.version+'-win-unsigned/'+args.signer]) 88 | subprocess.check_call(['git', 'add', args.version+'-osx-unsigned/'+args.signer]) 89 | subprocess.check_call(['git', 'commit', '-m', 'Add '+args.version+' unsigned sigs for '+args.signer]) 90 | os.chdir(workdir) 91 | 92 | def sign(): 93 | global args, workdir 94 | os.chdir('gitian-builder') 95 | 96 | if args.windows: 97 | print('\nSigning ' + args.version + ' Windows') 98 | subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../axe/contrib/gitian-descriptors/gitian-win-signer.yml']) 99 | print('\a') 100 | subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-signed', '--destination', '../gitian.sigs/', '../axe/contrib/gitian-descriptors/gitian-win-signer.yml']) 101 | subprocess.check_call('mv build/out/axecore-*win64-setup.exe ../axecore-binaries/'+args.version, shell=True) 102 | subprocess.check_call('mv build/out/axecore-*win32-setup.exe ../axecore-binaries/'+args.version, shell=True) 103 | 104 | if args.macos: 105 | print('\nSigning ' + args.version + ' MacOS') 106 | subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../axe/contrib/gitian-descriptors/gitian-osx-signer.yml']) 107 | print('\a') 108 | subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-signed', '--destination', '../gitian.sigs/', '../axe/contrib/gitian-descriptors/gitian-osx-signer.yml']) 109 | subprocess.check_call('mv build/out/axecore-osx-signed.dmg ../axecore-binaries/'+args.version+'/axecore-'+args.version+'-osx.dmg', shell=True) 110 | 111 | os.chdir(workdir) 112 | 113 | if args.commit_files: 114 | print('\nCommitting '+args.version+' Signed Sigs\n') 115 | os.chdir('gitian.sigs') 116 | subprocess.check_call(['git', 'add', args.version+'-win-signed/'+args.signer]) 117 | subprocess.check_call(['git', 'add', args.version+'-osx-signed/'+args.signer]) 118 | subprocess.check_call(['git', 'commit', '-a', '-m', 'Add '+args.version+' signed binary sigs for '+args.signer]) 119 | os.chdir(workdir) 120 | 121 | def verify(): 122 | global args, workdir 123 | os.chdir('gitian-builder') 124 | 125 | print('\nVerifying v'+args.version+' Linux\n') 126 | subprocess.call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-linux', '../axe/contrib/gitian-descriptors/gitian-linux.yml']) 127 | print('\nVerifying v'+args.version+' Windows\n') 128 | subprocess.call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-unsigned', '../axe/contrib/gitian-descriptors/gitian-win.yml']) 129 | print('\nVerifying v'+args.version+' MacOS\n') 130 | subprocess.call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-unsigned', '../axe/contrib/gitian-descriptors/gitian-osx.yml']) 131 | print('\nVerifying v'+args.version+' Signed Windows\n') 132 | subprocess.call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-signed', '../axe/contrib/gitian-descriptors/gitian-win-signer.yml']) 133 | print('\nVerifying v'+args.version+' Signed MacOS\n') 134 | subprocess.call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-signed', '../axe/contrib/gitian-descriptors/gitian-osx-signer.yml']) 135 | 136 | os.chdir(workdir) 137 | 138 | def main(): 139 | global args, workdir 140 | 141 | parser = argparse.ArgumentParser(usage='%(prog)s [options] signer version') 142 | parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch') 143 | parser.add_argument('-p', '--pull', action='store_true', dest='pull', help='Indicate that the version argument is the number of a github repository pull request') 144 | parser.add_argument('-u', '--url', dest='url', default='https://github.com/axerunners/axe', help='Specify the URL of the repository. Default is %(default)s') 145 | parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build') 146 | parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build') 147 | parser.add_argument('-s', '--sign', action='store_true', dest='sign', help='Make signed binaries for Windows and MacOS') 148 | parser.add_argument('-B', '--buildsign', action='store_true', dest='buildsign', help='Build both signed and unsigned binaries') 149 | parser.add_argument('-o', '--os', dest='os', default='lwm', help='Specify which Operating Systems the build is for. Default is %(default)s. l for Linux, w for Windows, m for MacOS') 150 | parser.add_argument('-j', '--jobs', dest='jobs', default='2', help='Number of processes to use. Default %(default)s') 151 | parser.add_argument('-m', '--memory', dest='memory', default='2000', help='Memory to allocate in MiB. Default %(default)s') 152 | parser.add_argument('-V', '--virtualization', dest='virtualization', default='docker', help='Specify virtualization technology to use: lxc for LXC, kvm for KVM, docker for Docker. Default is %(default)s') 153 | parser.add_argument('-S', '--setup', action='store_true', dest='setup', help='Set up the Gitian building environment. Only works on Debian-based systems (Ubuntu, Debian)') 154 | parser.add_argument('-D', '--detach-sign', action='store_true', dest='detach_sign', help='Create the assert file for detached signing. Will not commit anything.') 155 | parser.add_argument('-n', '--no-commit', action='store_false', dest='commit_files', help='Do not commit anything to git') 156 | parser.add_argument('signer', help='GPG signer to sign each build assert file') 157 | parser.add_argument('version', help='Version number, commit, or branch to build. If building a commit or branch, the -c option must be specified') 158 | 159 | args = parser.parse_args() 160 | workdir = os.getcwd() 161 | 162 | args.linux = 'l' in args.os 163 | args.windows = 'w' in args.os 164 | args.macos = 'm' in args.os 165 | 166 | args.is_bionic = b'bionic' in subprocess.check_output(['lsb_release', '-cs']) 167 | 168 | if args.buildsign: 169 | args.build = True 170 | args.sign = True 171 | 172 | args.sign_prog = 'true' if args.detach_sign else 'gpg --detach-sign' 173 | 174 | args.lxc = (args.virtualization == 'lxc') 175 | args.kvm = (args.virtualization == 'kvm') 176 | args.docker = (args.virtualization == 'docker') 177 | 178 | script_name = os.path.basename(sys.argv[0]) 179 | # Set all USE_* environment variables for gitian-builder: USE_LXC, USE_DOCKER and USE_VBOX 180 | os.environ['USE_VBOX'] = '' 181 | if args.lxc: 182 | os.environ['USE_LXC'] = '1' 183 | os.environ['USE_DOCKER'] = '' 184 | if 'GITIAN_HOST_IP' not in os.environ.keys(): 185 | os.environ['GITIAN_HOST_IP'] = '10.0.3.1' 186 | if 'LXC_GUEST_IP' not in os.environ.keys(): 187 | os.environ['LXC_GUEST_IP'] = '10.0.3.5' 188 | elif args.kvm: 189 | os.environ['USE_LXC'] = '' 190 | os.environ['USE_DOCKER'] = '' 191 | elif args.docker: 192 | os.environ['USE_LXC'] = '' 193 | os.environ['USE_DOCKER'] = '1' 194 | else: 195 | print(script_name+': Wrong virtualization option.') 196 | print('Try '+script_name+' --help for more information') 197 | exit(1) 198 | 199 | # Signer and version shouldn't be empty 200 | if args.signer == '': 201 | print(script_name+': Missing signer.') 202 | print('Try '+script_name+' --help for more information') 203 | exit(1) 204 | if args.version == '': 205 | print(script_name+': Missing version.') 206 | print('Try '+script_name+' --help for more information') 207 | exit(1) 208 | 209 | # Add leading 'v' for tags 210 | if args.commit and args.pull: 211 | raise Exception('Cannot have both commit and pull') 212 | args.commit = ('' if args.commit else 'v') + args.version 213 | 214 | if args.setup: 215 | setup() 216 | 217 | if not args.build and not args.sign and not args.verify: 218 | exit(0) 219 | 220 | # Disable for MacOS if no SDK found 221 | if args.macos and not os.path.isfile('gitian-builder/inputs/MacOSX10.11.sdk.tar.gz'): 222 | print('Cannot build for MacOS, SDK does not exist. Will build for other OSes') 223 | args.macos = False 224 | 225 | os.chdir('axe') 226 | if args.pull: 227 | subprocess.check_call(['git', 'fetch', args.url, 'refs/pull/'+args.version+'/merge']) 228 | os.chdir('../gitian-builder/inputs/axe') 229 | subprocess.check_call(['git', 'fetch', args.url, 'refs/pull/'+args.version+'/merge']) 230 | args.commit = subprocess.check_output(['git', 'show', '-s', '--format=%H', 'FETCH_HEAD'], universal_newlines=True, encoding='utf8').strip() 231 | args.version = 'pull-' + args.version 232 | print(args.commit) 233 | subprocess.check_call(['git', 'fetch']) 234 | subprocess.check_call(['git', 'checkout', args.commit]) 235 | os.chdir(workdir) 236 | 237 | if args.build: 238 | build() 239 | 240 | if args.sign: 241 | sign() 242 | 243 | if args.verify: 244 | verify() 245 | 246 | if __name__ == '__main__': 247 | main() 248 | -------------------------------------------------------------------------------- /roles/gitian/templates/gitian-lxc: -------------------------------------------------------------------------------- 1 | {{ gitian_user }} ALL=(ALL:ALL) NOPASSWD: ALL 2 | %sudo ALL=NOPASSWD: /usr/bin/lxc-start 3 | %sudo ALL=NOPASSWD: /usr/bin/lxc-execute 4 | -------------------------------------------------------------------------------- /roles/gitian/templates/gpg.conf: -------------------------------------------------------------------------------- 1 | no-greeting 2 | default-key {{ gpg_key_id }} 3 | require-cross-certification 4 | charset utf-8 5 | keyserver hkp://keys.gnupg.net 6 | use-agent 7 | keyid-format 0xlong 8 | no-emit-version 9 | -------------------------------------------------------------------------------- /roles/gitian/templates/lxc-net: -------------------------------------------------------------------------------- 1 | USE_LXC_BRIDGE="true" 2 | LXC_BRIDGE="lxcbr0" 3 | LXC_ADDR="10.0.3.1" 4 | LXC_NETMASK="255.255.255.0" 5 | LXC_NETWORK="10.0.3.0/24" 6 | LXC_DHCP_RANGE="10.0.3.2,10.0.3.254" 7 | LXC_DHCP_MAX="253" 8 | -------------------------------------------------------------------------------- /roles/gitian/templates/profile: -------------------------------------------------------------------------------- 1 | # ~/.profile: executed by the command interpreter for login shells. 2 | # This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login 3 | # exists. 4 | # see /usr/share/doc/bash/examples/startup-files for examples. 5 | # the files are located in the bash-doc package. 6 | 7 | # the default umask is set in /etc/profile; for setting the umask 8 | # for ssh logins, install and configure the libpam-umask package. 9 | #umask 022 10 | 11 | # if running bash 12 | if [ -n "$BASH_VERSION" ]; then 13 | # include .bashrc if it exists 14 | if [ -f "$HOME/.bashrc" ]; then 15 | . "$HOME/.bashrc" 16 | fi 17 | fi 18 | 19 | # set PATH so it includes user's private bin if it exists 20 | if [ -d "$HOME/bin" ] ; then 21 | PATH="$HOME/bin:$PATH" 22 | fi 23 | 24 | export DISTRO=debian 25 | export ARCH=amd64 26 | export USE_LXC=1 27 | export LXC_BRIDGE=lxcbr0 28 | export GITIAN_HOST_IP={{ gitian_host_ip }} 29 | export LXC_GUEST_IP={{ lxc_guest_ip }} 30 | export MIRROR_HOST={{ gitian_host_ip }} 31 | -------------------------------------------------------------------------------- /roles/gitian/templates/rc.local: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | echo 1 > /sys/fs/cgroup/cpuset/cgroup.clone_children 4 | echo 1 > /proc/sys/kernel/unprivileged_userns_clone 5 | echo 1 > /proc/sys/net/ipv4/ip_forward 6 | 7 | exit 0 8 | --------------------------------------------------------------------------------