├── .gitignore ├── README.md └── terraform ├── cloud-config.yml ├── terraform.tf ├── terraform.tfvars.example └── variables.tf /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.tfvars 3 | *.tfstate* 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vault on CoreOS + Docker with Terraform (on Digital Ocean) 2 | 3 | This will deploy [Vault](https://vaultproject.io) on [CoreOS](http://coreos.com/) using [my Vault Docker container](https://registry.hub.docker.com/u/sjourdan/vault/) with [Terraform](http://terraform.io/). 4 | 5 | A first version of this will use [demo.consul.io](https://demo.consul.io) as a backend, but using [docker-vault](https://github.com/sjourdan/docker-vault) it can easily be extended to a private [Consul](https://consul.io/) backend. 6 | 7 | Terraform will start/manage the CoreOS infrastructure, cloud-init will give enough information to start/join the cluster and deploy required files. Then fleet will manage the containers. 8 | 9 | You **will** need to generate a [new etcd discovery token](https://discovery.etcd.io/new) and enter it in the `terraform.tf` file for the demo to work. 10 | 11 | The file `cloud-config.yml` contains: 12 | * The Vault configuration file (`/home/core/config/demo.hcl`) 13 | * The two `fleet` unit service files (`/home/core/services/vault@.service` and `/home/core/services/vault-discovery@.service`) 14 | * enough to start `etcd` and `fleet` 15 | 16 | ## Deploy the base infrastructure 17 | 18 | Fill in the blanks in the configuration file: 19 | 20 | $ cp terraform.tfvars.example terraform.tfvars 21 | $ terraform apply 22 | 23 | ## CoreOS 24 | 25 | Login and check `fleetctl` sees all the cluster machines: 26 | 27 | fleetctl list-machines 28 | MACHINE IP METADATA 29 | 6147c03d... 10.133.169.81 - 30 | [...] 31 | 32 | Units are empty: 33 | 34 | fleetctl list-units 35 | UNIT MACHINE ACTIVE SUB 36 | 37 | The unit files are empty: 38 | 39 | fleetctl list-unit-files 40 | UNIT HASH DSTATE STATE TARGET 41 | 42 | ### Vault Service (Unit) Files 43 | 44 | Submit the service files sent by cloud-config under `services/`: 45 | 46 | fleetctl submit services/vault\@.service services/vault-discovery\@.service 47 | 48 | Now we have unit files: 49 | 50 | fleetctl list-unit-files 51 | UNIT HASH DSTATE STATE TARGET 52 | vault-discovery@.service d15726b inactive inactive - 53 | vault@.service de5c96e inactive inactive - 54 | 55 | We want to start a Vault service on TCP/8200: 56 | 57 | fleetctl load vault@8200.service 58 | Unit vault@8200.service loaded on 6147c03d.../10.133.169.81 59 | 60 | fleetctl load vault-discovery@8200.service 61 | Unit vault-discovery@8200.service loaded on 6147c03d.../10.133.169.81 62 | 63 | ### Start the Vault Service 64 | 65 | Transfer the Vault configuration file from `config/` over to `/home/core/config` 66 | 67 | fleetctl start vault@8200.service 68 | Unit vault@8200.service launched on 6147c03d.../10.133.169.81 69 | 70 | Check the status: 71 | 72 |
 73 | fleetctl status vault@8200.service
 74 | ● vault@8200.service - Vault Service
 75 |    Loaded: loaded (/run/fleet/units/vault@8200.service; linked-runtime; vendor preset: disabled)
 76 |    Active: active (running) since Tue 2015-05-05 21:04:15 UTC; 2s ago
 77 | May 05 21:04:15 core-1 docker[1628]: fdaa9c66787e: Download complete
 78 | May 05 21:04:15 core-1 docker[1628]: fdaa9c66787e: Download complete
 79 | May 05 21:04:15 core-1 docker[1628]: Status: Image is up to date for sjourdan/vault:latest
 80 | May 05 21:04:15 core-1 systemd[1]: Started Vault Service.
 81 | May 05 21:04:15 core-1 docker[1637]: ==> Vault server configuration:
 82 | May 05 21:04:15 core-1 docker[1637]: Log Level: info
 83 | May 05 21:04:15 core-1 docker[1637]: Mlock: supported: true, enabled: true
 84 | May 05 21:04:15 core-1 docker[1637]: Backend: consul (HA available)
 85 | May 05 21:04:15 core-1 docker[1637]: Listener 1: tcp (addr: "0.0.0.0:8200", tls: "disabled")
 86 | May 05 21:04:15 core-1 docker[1637]: ==> Vault server started! Log data will stream in below:
 87 | 
88 | 89 | Get from etcd the public IP and port to use: 90 | 91 | etcdctl get /announce/services/vault8200 92 | 188.166.87.74:8200 93 | 94 | ### Use the Vault Service 95 | 96 | On your workstation you can now use Vault: 97 | 98 | export VAULT_ADDR='http://188.166.87.74:8200' 99 | vault init 100 | vault --help 101 | 102 | ### Vault Container Logs 103 | 104 | Tail the 100 last line of container's logs: 105 | 106 | fleetctl journal -lines=100 -f vault@8200.service 107 | -- Logs begin at Tue 2015-05-05 17:13:23 UTC, end at Tue 2015-05-05 17:19:14 UTC. -- 108 | [...] 109 | 110 | If needed, attach a terminal to debug: 111 | 112 | docker exec -t -i /bin/sh 113 | 114 | ### Stop the service 115 | 116 | fleetctl stop vault@8200.service 117 | 118 | ### Destroy the Service Unit files 119 | 120 | If needed: 121 | 122 | fleetctl destroy vault@8200.service 123 | fleetctl destroy vault@.service 124 | 125 | ### Destroy the demo infrastructure. 126 | 127 | terraform destroy 128 | 129 | ## Debug 130 | 131 | To get the etcd discovery address: 132 | 133 | grep DISCOVERY /run/systemd/system/etcd.service.d/20-cloudinit.conf 134 | 135 | To try to validate the cloud-config.yml: [validator](https://coreos.com/validate/) 136 | 137 | To apply a new cloudinit: 138 | 139 | sudo /usr/bin/coreos-cloudinit --oem=digitalocean 140 | sudo /usr/bin/coreos-cloudinit --from-file conf.yml 141 | -------------------------------------------------------------------------------- /terraform/cloud-config.yml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | write_files: 3 | - path: /home/core/config/demo.hcl 4 | content: | 5 | backend "consul" { 6 | address = "demo.consul.io:80" 7 | path = "demo_vault_changeme" 8 | advertise_addr = "http://127.0.0.1" 9 | } 10 | 11 | listener "tcp" { 12 | address = "0.0.0.0:8200" 13 | tls_disable = 1 14 | } 15 | - path: /home/core/services/vault@.service 16 | content: | 17 | [Unit] 18 | Description=Vault Service 19 | After=etcd.service 20 | After=docker.service 21 | Requires=vault-discovery@%i.service 22 | 23 | [Service] 24 | TimeoutStartSec=0 25 | KillMode=none 26 | EnvironmentFile=/etc/environment 27 | ExecStartPre=-/usr/bin/docker kill vault%i 28 | ExecStartPre=-/usr/bin/docker rm vault%i 29 | ExecStartPre=/usr/bin/docker pull sjourdan/vault 30 | ExecStart=/usr/bin/docker run --cap-add IPC_LOCK --hostname vault%i --name vault%i --volume /home/core/config:/config -p ${COREOS_PUBLIC_IPV4}:%i:8200 sjourdan/vault -config=/config/demo.hcl 31 | ExecStop=/usr/bin/docker stop vault%i 32 | 33 | [X-Fleet] 34 | X-Conflicts=vault@*.service 35 | - path: /home/core/services/vault-discovery@.service 36 | content: | 37 | [Unit] 38 | Description=Announce Vault@%i service 39 | BindsTo=vault@%i.service 40 | 41 | [Service] 42 | EnvironmentFile=/etc/environment 43 | ExecStart=/bin/sh -c "while true; do /usr/bin/etcdctl set /announce/services/vault%i ${COREOS_PUBLIC_IPV4}:%i --ttl 60; sleep 45; done" 44 | ExecStop=/usr/bin/etcdctl rm /announce/services/vault%i 45 | 46 | [X-Fleet] 47 | X-ConditionMachineOf=vault@%i.service 48 | coreos: 49 | etcd: 50 | # generate a new token for each cluster: https://discovery.etcd.io/new 51 | discovery: https://discovery.etcd.io/fcc9c66458df3576daedffa38f0855f1 52 | # multi-region and multi-cloud deployments need to use $public_ipv4 53 | advertise-client-urls: http://$private_ipv4:2379 54 | listen-client-urls: http://0.0.0.0:2379 55 | listen-peer-urls: http://$private_ipv4:2380 56 | fleet: 57 | public-ip: $private_ipv4 58 | units: 59 | - name: etcd.service 60 | command: start 61 | - name: fleet.service 62 | command: start 63 | -------------------------------------------------------------------------------- /terraform/terraform.tf: -------------------------------------------------------------------------------- 1 | # Configure the DigitalOcean Provider 2 | provider "digitalocean" { 3 | token = "${var.do_token}" 4 | } 5 | 6 | # Create a new SSH key 7 | resource "digitalocean_ssh_key" "default" { 8 | name = "DO SSH Key" 9 | public_key = "${file("${var.ssh_key_file}.pub")}" 10 | } 11 | 12 | # Create a new vault droplet 13 | resource "digitalocean_droplet" "coreos-1" { 14 | image = "coreos-beta" 15 | name = "core-1" 16 | region = "ams3" 17 | size = "512mb" 18 | ssh_keys = ["${digitalocean_ssh_key.default.id}"] 19 | private_networking = true 20 | user_data = "${file("cloud-config.yml")}" 21 | } 22 | 23 | output "core-1.ipv4_address" { 24 | value = "${digitalocean_droplet.coreos-1.ipv4_address}" 25 | } 26 | -------------------------------------------------------------------------------- /terraform/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | do_token = "123456" 2 | ssh_key_file = "~/.ssh/somekey" 3 | -------------------------------------------------------------------------------- /terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "do_token" {} 2 | variable "ssh_key_file" {} 3 | --------------------------------------------------------------------------------