Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ageis committed Oct 17, 2016
0 parents commit 4c20410
Show file tree
Hide file tree
Showing 32 changed files with 1,042 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -0,0 +1,4 @@
.vagrant/*
*.swp
gitian.sigs/*
zcash-binaries/*
104 changes: 104 additions & 0 deletions README.md
@@ -0,0 +1,104 @@
Zcash deterministic builds
==========================

This is a deterministic build environment for [Zcash](https://github.com/zcash/zcash/) that uses [Gitian](https://gitian.org/).

Gitian provides a way to be reasonably certain that the Zcash 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.

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 is accepted.

More independent Gitian builders are needed, which is why this guide exists.

Requirements
------------

4GB of RAM, at least two cores

It relies upon [Vagrant](https://www.vagrantup.com/downloads.html) and [VirtualBox](https://www.virtualbox.org/wiki/Linux_Downloads) plus [Ansible](https://www.ansible.com/), which can be installed via Python's [pip](https://bootstrap.pypa.io/get-pip.py). Try `sudo pip install -U ansible`.

If you use Linux, then we recommend obtaining VirtualBox through your package manager instead of the Oracle website.

How to get started
------------------

### Settings in gitian.yml

```yaml
# URL of repository containing Zcash source code.
zcash_git_repo_url: 'https://github.com/zcash/zcash'

# Specific tag or branch you want to build.
zcash_version: 'master'

# The name@ in the e-mail address of your GPG key, alternatively a key ID.
gpg_key_name: ''

# Equivalent to git --config user.name & user.email
git_name: ''
git_email: ''

# OPTIONAL set to import your GPG key into the VM.
gpg_key_id: ''

# OPTIONAL set to import your SSH key into the VM. Example: id_rsa, id_ed25519. Assumed to reside in ~/.ssh
ssh_key_name: ''
```

Make sure VirtualBox, Vagrant and Ansible are installed, and then run:

vagrant up --provision zcash-build

This will provision a Gitian host virtual machine that uses a Linux container (LXC) guest to perform the actual builds.

Building Zcash
--------------

vagrant ssh zcash-build
./gitian-build.sh

The output from `gbuild` is informative. There are some common warnings which can be ignored, e.g. if you get a 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.

Take a look at the variables near the top of `~/gitian-build.sh` and get familiar with its functioning, as it can handle most tasks.

Generating and uploading signatures
-----------------------------------

After the build successfully completes, `gsign` will be called. Commit and push your signatures (both the .assert and .assert.sig files) to the [zcash/gitian.sigs](https://github.com/zcash/gitian.sigs) repository, or if that's not possible then create a pull request.

Working with GPG and SSH
--------------------------

We provide two options for automatically importing keys into the VM, or you may choose to copy them manually. Keys are needed A) to sign the manifests which get pushed to [gitian.sigs](https://github.com/zcash/gitian.sigs) and B) to interact with GitHub, if you choose to use an SSH instead of HTTPS remote. The latter would entail always providing your GitHub login and access token in order to push from within the VM.

Your local SSH agent is automatically forwarded into the VM via a configuration option. If you run ssh-agent, your keys should already be available.

GPG is trickier, 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:

vagrant plugin install vagrant-sshfs

Uncomment the line beginning with `gitian.vm.synced_folder "~/.gnupg"` in `Vagrantfile`. Ensure the destination mount point is empty. Then run:

vagrant sshfs --mount zcash-build

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.


Copying files
-------------

You can use the provided script `scp.sh`. Another way to do it is with a plugin.

vagrant plugin install vagrant-scp

To copy files to the VM: `vagrant scp file_on_host.txt :file_on_vm.txt`

To copy files from the VM: `vagrant scp :file_on_vm.txt file_on_host.txt`

Other notes
-----------

Port 2200 on the host machine should be forwarded to port 22 on the guest virtual machine.

The automation and configuration management assumes that VirtualBox will assign the IP address `10.0.2.15` to the Gitian host Vagrant VM.

Tested with Ansible 2.1.2 and Vagrant 1.8.6 on Debian GNU/Linux (jessie).
25 changes: 25 additions & 0 deletions Vagrantfile
@@ -0,0 +1,25 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|

config.ssh.forward_agent = true
config.vm.define 'zcash-build', autostart: false do |gitian|
gitian.vm.box = "debian/jessie64"
gitian.vm.network "forwarded_port", guest: 22, host: 2200, auto_correct: true
gitian.vm.provision "ansible" do |ansible|
ansible.playbook = "gitian.yml"
ansible.verbose = 'v'
ansible.raw_arguments = Shellwords.shellsplit(ENV['ANSIBLE_ARGS']) if ENV['ANSIBLE_ARGS']
end
gitian.vm.provider "virtualbox" do |v|
v.name = "zcash-build"
v.memory = 4096
v.cpus = 2
end
# gitian.vm.synced_folder "~/.gnupg", "/home/vagrant/.gnupg", type: "sshfs"
# gitian.vm.synced_folder "./gitian.sigs", "/home/vagrant/gitian.sigs", create: true
# gitian.vm.synced_folder "./zcash-binaries", "/home/vagrant/zcash-binaries", create: true
gitian.vm.post_up_message = "Zcash deterministic build environment started."
end

end
11 changes: 11 additions & 0 deletions ansible.cfg
@@ -0,0 +1,11 @@
[defaults]
inventory = inventory
retry_files_enabled = False
roles_path = roles
host_key_checking = False
timeout = 60

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=300s -o ConnectTimeout=60
pipelining = True
scp_if_ssh = True
13 changes: 13 additions & 0 deletions forward_gpg_agent.sh
@@ -0,0 +1,13 @@
#!/bin/bash -e

GPG_SOCK=$(echo "$GPG_AGENT_INFO" | cut -d: -f1)
if [ -z "$GPG_SOCK" ] ; then
echo "No GPG agent configured - this won't work out." >&2
exit 1
fi

vagrant ssh zcash-build -- rm -f /home/vagrant/.gnupg/S.gpg-agent
vagrant ssh zcash-build -- -t \
-R /home/vagrant/.gnupg/S.gpg-agent:$GPG_SOCK \
-o StreamLocalBindUnlink=yes \
-o ExitOnForwardFailure=yes
17 changes: 17 additions & 0 deletions gitian.yml
@@ -0,0 +1,17 @@
---
- name: Apply the Zcash Gitian builder role.
become: yes
hosts: localhost:zcash-build
vars:
zcash_git_repo_url: https://github.com/zcash/zcash
zcash_version: v1.0.0-rc1
gpg_key_name: ''
git_name: ''
git_email: ''
gpg_key_id: '' # optional
ssh_key_name: '' # optional
roles:
- role: common
tags: common
- role: gitian
tags: gitian
19 changes: 19 additions & 0 deletions roles/common/defaults/main.yml
@@ -0,0 +1,19 @@
---
zcash_swapfile_size: 2G
zcash_vm_swappiness: 10
zcash_common_packages:
- apt-show-versions
- apt-transport-https
- curl
- git-core
- haveged
- htop
- ntp
- ntpdate
- python-pip
- rsync
- screen
- sudo
- tmux
- tree
- vim
5 changes: 5 additions & 0 deletions roles/common/files/02periodic
@@ -0,0 +1,5 @@
APT::Periodic::Enable "1";
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
6 changes: 6 additions & 0 deletions roles/common/files/50unattended-upgrades
@@ -0,0 +1,6 @@
Unattended-Upgrade::Origins-Pattern {
"o=Debian,n=jessie-updates";
"o=Debian,n=jessie,l=Debian-Security";
};
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
3 changes: 3 additions & 0 deletions roles/common/handlers/main.yml
@@ -0,0 +1,3 @@
---
- name: update timezone
command: dpkg-reconfigure --frontend noninteractive tzdata
14 changes: 14 additions & 0 deletions roles/common/tasks/add_github_ssh_hostkey.yml
@@ -0,0 +1,14 @@
---
- name: Look up GitHub SSH host key.
local_action: command ssh-keyscan -t rsa github.com
register: github_ssh_keyscan_result
changed_when: false
always_run: yes
run_once: yes
become: no

- name: Ensure github.com is a known host.
known_hosts:
path: /etc/ssh/ssh_known_hosts
name: github.com
key: "{{ github_ssh_keyscan_result.stdout }}"
14 changes: 14 additions & 0 deletions roles/common/tasks/auto_upgrades.yml
@@ -0,0 +1,14 @@
---
- name: Copy unattended-upgrades configuration.
copy:
dest: /etc/apt/apt.conf.d/
src: "{{ item }}"
mode: "0640"
owner: root
group: root
with_items:
- 02periodic
- 50unattended-upgrades

- name: Enable automatic updates in unattended-upgrades package config.
shell: echo unattended-upgrades unattended-upgrades/enable_auto_updates boolean true | debconf-set-selections
11 changes: 11 additions & 0 deletions roles/common/tasks/hostname.yml
@@ -0,0 +1,11 @@
---
- name: Set hostname.
hostname:
name: "zcash-build"

- name: Build /etc/hosts file.
lineinfile:
dest: /etc/hosts
regexp: '^127.0.1.1'
line: "127.0.1.1 zcash-build"
state: present
8 changes: 8 additions & 0 deletions roles/common/tasks/main.yml
@@ -0,0 +1,8 @@
---
- include: update_everything.yml
- include: packages.yml
- include: make_swap.yml
- include: add_github_ssh_hostkey.yml
- include: hostname.yml
- include: motd.yml
- include: auto_upgrades.yml
37 changes: 37 additions & 0 deletions roles/common/tasks/make_swap.yml
@@ -0,0 +1,37 @@
---
- name: Check whether swap file already exists.
stat:
path: /swapfile
register: existing_swapfile_result

- name: Allocate swapfile.
command: "fallocate -l {{ zcash_swapfile_size }} /swapfile"
when: not existing_swapfile_result.stat.exists

- name: Set permissions of swapfile.
file:
path: /swapfile
owner: root
group: root
mode: "0600"
state: touch

- name: Set up the swapfile.
command: mkswap /swapfile
when: not existing_swapfile_result.stat.exists

- name: Enable the swapfile.
command: swapon /swapfile
when: not existing_swapfile_result.stat.exists

- name: Make the swapfile persistent.
lineinfile:
dest: /etc/fstab
regexp: "^/swapfile"
line: "/swapfile none swap sw 0 0"

- name: Set vm.swappiness in sysctl.
sysctl:
name: vm.swappiness
value: "{{ zcash_vm_swappiness }}"
state: present
12 changes: 12 additions & 0 deletions roles/common/tasks/motd.yml
@@ -0,0 +1,12 @@
---
- name: Get the current kernel version string.
command: uname -a
register: kernel_version_string

- name: Install motd (message of the day).
template:
src: motd.j2
dest: /etc/motd
owner: root
group: root
mode: "0644"
8 changes: 8 additions & 0 deletions roles/common/tasks/packages.yml
@@ -0,0 +1,8 @@
---
- name: Install some common packages.
apt:
name: "{{ item }}"
state: present
update_cache: yes
cache_valid_time: 3600
with_items: "{{ zcash_common_packages }}"
50 changes: 50 additions & 0 deletions roles/common/tasks/update_everything.yml
@@ -0,0 +1,50 @@
---
- name: Check if sudo is installed.
command: dpkg-query -l sudo
register: sudo_installed_result
# dpkg returns 1 if package not found,
# so disable the scary red text by setting no-fail mode.
# The output from the command is checked in the next task.
failed_when: false
changed_when: false
# Necessary to support --check mode
always_run: true

- name: Install sudo.
apt:
name: sudo
state: present
update_cache: yes
cache_valid_time: 3600
when: "'no packages found' in sudo_installed_result.stderr"

- name: Update apt cache.
apt:
update_cache: yes
cache_valid_time: 3600

- name: Install aptitude.
apt:
name: aptitude
state: present
update_cache: yes
cache_valid_time: 3600

- name: Perform aptitude safe-upgrade.
apt:
upgrade: safe
update_cache: yes
cache_valid_time: 3600
tags: apt

- name: Remove unneeded packages.
command: apt-get autoremove -y
register: autoremove_result
changed_when: "'0 upgraded' not in autoremove_result.stdout"
tags: apt

- name: Clean the apt cache.
command: apt-get autoclean
register: autoclean_result
changed_when: "'Del' in autoclean_result.stdout"
tags: apt

0 comments on commit 4c20410

Please sign in to comment.