├── home ├── .ssh │ └── config └── bin │ └── expect-ssh-add.sh ├── Dockerfile └── README.md /home/.ssh/config: -------------------------------------------------------------------------------- 1 | Host * 2 | StrictHostKeyChecking no 3 | UserKnownHostsFile=/dev/null 4 | -------------------------------------------------------------------------------- /home/bin/expect-ssh-add.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/expect -f 2 | 3 | set file_name [lindex $argv 0] 4 | set passphrase [lindex $argv 1] 5 | 6 | spawn ssh-add /root/.ssh/$file_name 7 | expect "Enter passphrase for /root/.ssh/$file_name:" 8 | send $passphrase\n 9 | expect "Identity added" 10 | interact 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | ENV HOME=/root 4 | ARG DEBIAN_FRONTEND=noninteractive 5 | 6 | # Prepare required utilities for APT packages installation 7 | ########################################################## 8 | 9 | RUN apt-get -q update && \ 10 | apt-get install -q -y --no-install-recommends \ 11 | curl \ 12 | software-properties-common \ 13 | sudo && \ 14 | # Clean up APT when done 15 | apt-get clean && apt-get -y autoremove && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 16 | 17 | # Prepare APT package repositories 18 | ################################## 19 | 20 | RUN \ 21 | ## Ansible 22 | apt-add-repository ppa:ansible/ansible && \ 23 | ## NodeSource 24 | curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - && \ 25 | ## Yarn 26 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - && \ 27 | echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list && \ 28 | # Clean up APT when done 29 | apt-get clean && apt-get -y autoremove && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 30 | 31 | # Install APT packages 32 | ###################### 33 | 34 | RUN apt-get -q update && \ 35 | apt-get install -q -y --no-install-recommends \ 36 | ## Ansible 37 | ansible \ 38 | rsync \ 39 | ## NodeJS & yarn 40 | nodejs \ 41 | yarn \ 42 | ## Sage 43 | libpng-dev \ 44 | libpng16-16 \ 45 | ## Misc 46 | expect \ 47 | git \ 48 | ssh-client && \ 49 | # Clean up APT when done 50 | apt-get clean && apt-get -y autoremove && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 51 | 52 | # Prepare SSH 53 | ############# 54 | 55 | COPY ./home/ $HOME/ 56 | RUN ln -s $HOME/bin/* /usr/local/bin/ 57 | 58 | CMD ["bash"] 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **[Deprecated] Use [ItinerisLtd/tiller-circleci-orb](https://github.com/ItinerisLtd/tiller-circleci-orb) instead.** 2 | 3 | --- 4 | 5 | # Tiller 6 | 7 | Deploy Trellis, Bedrock and Sage via AWS CodeBuild. 8 | 9 | 10 | 11 | 12 | 13 | - [Requirements](#requirements) 14 | - [What's in the box?](#whats-in-the-box) 15 | - [Set Up](#set-up) 16 | - [GitHub](#github) 17 | - [Trellis](#trellis) 18 | - [`buildspec.yml`](#buildspecyml) 19 | - [AWS CodeBuild](#aws-codebuild) 20 | - [Docker Image](#docker-image) 21 | - [Environment Variables](#environment-variables) 22 | - [`PRIVATE_KEY` & `PRIVATE_KEY_PASSPHRASE`](#private_key--private_key_passphrase) 23 | - [`SITE_ENV` & `SITE_KEY`](#site_env--site_key) 24 | - [Examples](#examples) 25 | - [Docker Image](#docker-image-1) 26 | - [FAQ](#faq) 27 | - [Is it a must to use all Trellis, Bedrock and Sage?](#is-it-a-must-to-use-all-trellis-bedrock-and-sage) 28 | - [Is it a must to use AWS CodeBuild?](#is-it-a-must-to-use-aws-codebuild) 29 | - [Is it a must to use GitHub?](#is-it-a-must-to-use-github) 30 | - [Can I use multiple SSH key pairs?](#can-i-use-multiple-ssh-key-pairs) 31 | - [What does S3 bucket cache?](#what-does-s3-bucket-cache) 32 | - [Author Information](#author-information) 33 | - [Feedback](#feedback) 34 | 35 | 36 | 37 | ## Requirements 38 | 39 | - Trellis [b556ccd](https://github.com/roots/trellis/commit/b556ccdb2b3183eba4a9530b206a402422deeca3) or later 40 | - (Optional) Bedrock [ef090b6](https://github.com/roots/bedrock/commit/ef090b63ca0b772390a1db03cc7c118af20e8733) or later 41 | - (Optional) Sage [9.0.1](https://github.com/roots/sage/releases/tag/9.0.1) or later 42 | - (Optional) AWS [CodeBuild](https://aws.amazon.com/codebuild/) 43 | 44 | ## What's in the box? 45 | 46 | - A docker image to run deployment 47 | - [buildspec.yml](https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html) examples 48 | 49 | ## Set Up 50 | 51 | You need a robot user for deployment. In this example, we will use a GitHub machine user account as our robot. For simplicity, this robot uses the same SSH key pair to access both GitHub private repos and the web server. 52 | 53 | ### GitHub 54 | 55 | 1. Sign up a machine user on GitHub 56 | 1. Grant `mybot` **read** access to all necessary private repos 57 | 1. Generate a SSH key pair 58 | - `ssh-keygen -t ed25519 -C "mybot-$(date)"` 59 | - It must use a passphrase 60 | 1. [Upload the public key to Github](https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/) 61 | 62 | ### Trellis 63 | 64 | 1. Add the SSH key to web server 65 | ```yml 66 | # group_vars//users.yml 67 | users: 68 | - name: "{{ web_user }}" 69 | groups: 70 | - "{{ web_group }}" 71 | keys: 72 | - https://github.com/human.keys 73 | - https://github.com/mybot.keys # <-- This line 74 | - name: "{{ admin_user }}" 75 | groups: 76 | - sudo 77 | keys: 78 | - https://github.com/human.keys 79 | ``` 80 | 1. Re-provision 81 | `ansible-playbook server.yml -e env= --tags users` 82 | 83 | ### `buildspec.yml` 84 | 85 | Tiller comes with 2 different `buildspec.yml` examples. They are expecting different Trellis and Bedrock structures. 86 | 87 | Use `buildspec.yml` if your directory structure follow [the official documents](https://roots.io/trellis/docs/installing-trellis/#create-a-project): 88 | ``` 89 | example.com/ # → Root folder for the project 90 | ├── .git/ # → Only one git repo 91 | ├── trellis/ # → Your clone of roots/trellis, directory name must be `trellis` 92 | └── site/ # → A Bedrock-based WordPress site, directory name doesn't matter 93 | ``` 94 | 95 | [`buildspec.itineris.yml`](./buildspec.itineris.yml) do extra steps for itineris-specific project setup. 96 | 97 | At [Itineris](https://www.itineris.co.uk/), we use a opinionated project structure: 98 | - separate Trellis and Bedrock as 2 different git repo 99 | - name the Bedrock-based WordPress site directory more creatively, i.e: `bedrock` 100 | - extra deploy command parameter for our SSH bastion host, i.e: `-e bastion_user=$BASTION_USER` 101 | 102 | ``` 103 | example.com/ # → Root folder for the project 104 | ├── bedrock/ # → A Bedrock-based WordPress site, directory name must be `bedrock` 105 | │   └── .git/ # Bedrock git repo 106 | └── trellis/ # → Clone of roots/trellis, directory name must be `trellis` 107 | └── .git/ # Trellis git repo 108 | ``` 109 | 110 | See: [roots/trellis#883 (comment)](https://github.com/roots/trellis/issues/883#issuecomment-329052189) 111 | 112 | To install: 113 | - Option A: Use the `buildspec.yml` in the source code root directory 114 | 1. Copy and commit the `.yml` file to project root 115 | 1. Review the `.yml` file, change if necessary 116 | 1. Enter the `.yml` file name on AWS web console 117 | 118 | - Option B: Insert build commands via AWS web console 119 | 1. Copy and paste the `.yml` file to AWS web console 120 | 1. Review the commands, change if needed 121 | 122 | ### AWS CodeBuild 123 | 124 | #### Docker Image 125 | 126 | Use [`itinerisltd/tiller`](https://hub.docker.com/r/itinerisltd/tiller/). See [below](#docker-image-1). 127 | 128 | #### Environment Variables 129 | 130 | | Name | Value | Type | | 131 | | --------------------- | -------------------------- | --------------- | ------------------------------ | 132 | | PRIVATE_KEY | /ssm/the-private-key | Parameter Store | | 133 | | PRIVATE_KEY_PASSPHRASE | /ssm/the-passphrase | Parameter Store | | 134 | | SITE_ENV | production | Plaintext | | 135 | | SITE_KEY | example.com | Plaintext | | 136 | | BASTION_USER | mybot | Plaintext | `buildspec.itineris.yml ` only, omit `BASTION_USER` for Kinsta | 137 | | TRELLIS_REPO | git@github.com:xxx/yyy.git | Plaintext | `buildspec.itineris.yml ` only | 138 | 139 | ##### `PRIVATE_KEY` & `PRIVATE_KEY_PASSPHRASE` 140 | 141 | Encrypt `PRIVATE_KEY` and `PRIVATE_KEY_PASSPHRASE` with [AWS Systems Manager Parameter Store and AWS KMS](https://docs.aws.amazon.com/kms/latest/developerguide/services-parameter-store.html). **Never save them in plaintext!** 142 | 143 | 144 | `PRIVATE_KEY` needs line break characters(`\n`) For example: 145 | ```bash 146 | ➜ cat ~/.ssh/mybot 147 | -----BEGIN OPENSSH PRIVATE KEY----- 148 | aaa 149 | bbb 150 | ccc 151 | -----END OPENSSH PRIVATE KEY----- 152 | ``` 153 | 154 | Then, save `PRIVATE_KEY` as: 155 | ``` 156 | -----BEGIN OPENSSH PRIVATE KEY-----\naaa\nbbb\nccc\n-----END OPENSSH PRIVATE KEY----- 157 | ``` 158 | 159 | #### `SITE_ENV` & `SITE_KEY` 160 | 161 | They are used to build the final deploy command: 162 | ```bash 163 | # ansible-playbook deploy.yml -e env=$SITE_ENV -e site=$SITE_KEY -vvvv 164 | ➜ ansible-playbook deploy.yml -e env=production -e site=example.com -vvvv 165 | ``` 166 | 167 | #### Examples 168 | 169 | ![](./buildspec-yml.png) 170 | 171 | 172 | ![](./buildspec-itineris-yml.png) 173 | 174 | ### Docker Image 175 | 176 | Tiller comes with a [docker image](https://hub.docker.com/r/itinerisltd/tiller/) to run Trellis deployment: 177 | - Ubuntu 16.04 178 | - libpng-dev 179 | - libpng16-16 180 | - NodeJS v8 181 | - Yarn 182 | - Anisble 183 | - Git 184 | - [expect-ssh-add.sh](./expect-ssh-add.sh) 185 | 186 | This is sufficient for deploying a default Trellis, Bedrock and Sage project. You can build your own docker image if necessary: 187 | 188 | ```bash 189 | # Modify `Dockerfile` 190 | 191 | # Build the image without caches 192 | # Not using caches because we want latest packages to be installed 193 | ➜ docker build --no-cache --compress --tag tiller . 194 | 195 | # Tag the image 196 | ➜ docker tag tiller itinerisltd/tiller:2018.5.18.2 197 | ➜ docker tag tiller itinerisltd/tiller:latest 198 | 199 | # Push the image 200 | ➜ docker push itinerisltd/tiller:2018.5.18.2 201 | ➜ docker push itinerisltd/tiller:latest 202 | ``` 203 | 204 | ## FAQ 205 | 206 | ### Is it a must to use all Trellis, Bedrock and Sage? 207 | 208 | No, you don't need all of them. Only Trellis is required. 209 | 210 | ### Is it a must to use AWS CodeBuild? 211 | 212 | No. You can use the docker image without AWS CodeBuild. 213 | 214 | ### Is it a must to use GitHub? 215 | 216 | No. 217 | 218 | ### Can I use multiple SSH key pairs? 219 | 220 | Yes. 221 | 222 | ```yaml 223 | phases: 224 | pre_build: 225 | commands: 226 | - echo "$PRIVATE_KEY" > $HOME/.ssh/id_rsa 227 | - echo "$PRIVATE_KEY_SECOND" > $HOME/.ssh/id_rsa_second 228 | - chmod 600 $HOME/.ssh/id_rsa* 229 | - expect-ssh-add.sh id_rsa $PRIVATE_KEY_PASSPHRASE 230 | - expect-ssh-add.sh id_rsa_second $PRIVATE_KEY_PASSPHRASE_SECOND 231 | ``` 232 | 233 | ### What does S3 bucket cache? 234 | 235 | By default only yarn packages are cached. It speeds up the build by 20~60 seconds. 236 | This is optional and you can add more `cache.paths`. 237 | 238 | ## Author Information 239 | 240 | [Tiller](https://github.com/ItinerisLtd/tiller) is a [Itineris Limited](https://www.itineris.co.uk/) project created by [Tang Rufus](https://typist.tech). 241 | 242 | Special thanks to [the Roots team](https://roots.io/about/) whose [Trellis](https://github.com/roots/trellis) make this project possible. 243 | 244 | Full list of contributors can be found [here](https://github.com/ItinerisLtd/tiller/graphs/contributors). 245 | 246 | ## Feedback 247 | 248 | **Please provide feedback!** We want to make this library useful in as many projects as possible. 249 | Please submit an [issue](https://github.com/ItinerisLtd/tiller/issues/new) and point out what you do and don't like, or fork the project and make suggestions. 250 | **No issue is too small.** 251 | --------------------------------------------------------------------------------