diff --git a/README.md b/README.md
index 251710b..cf7d56a 100644
--- a/README.md
+++ b/README.md
@@ -49,81 +49,29 @@ sudo install -m755 /tmp/ebs-bootstrap /usr/local/sbin/ebs-bootstrap
## Documentation
-
-
+
+
## Use Cases
### `cloud-init`
-By default, `ebs-bootstrap` consumes a configuration file located at `/etc/ebs-boostrap/config.yml`. `cloud-init` can be configured to write a config to this location, using the `write_files` module. Ensure that `ebs-bootstrap` is installed on your Instance via the process of baking it into your Golden AMI or downloading it early in the boot process, using the `bootcmd` module.
-
The advent of Instance Store provided Nitro-enabled EC2 instances the ability to harness the power of high speed NVMe. For a stateful workload like a database, you might want a fast and ephemeral space for temporary tables, alongside a stateful EBS volume declared in a different CloudFormation Stack. However, these Instance Store devices were ephemeral and had to be formatted and mounted on each startup cycle.
-From the perspective of a **sceptical** Platforms Engineer, you do not mind a tool like `ebs-bootstrap` automating the task of formatting and mounting an ephemeral device. However, you personally draw the line on automation executing modifications to a stateful device, **without** the prior consent of a human. `ebs-bootstrap` empowers this Platform Engineer by allowing them to specify the execution mode, on a **device-by-device** basis: Instance Store (`force`) and EBS Volume (`healthcheck`)
-
-```yaml
-Parameters:
- LatestUbuntuAmi:
- Type: AWS::SSM::Parameter::Value
- Default: /aws/service/canonical/ubuntu/server/20.04/stable/current/amd64/hvm/ebs-gp2/ami-id
-
-Resources:
- Instance:
- Type: AWS::EC2::Instance
- Properties:
- ...
- ImageId: !Ref LatestUbuntuAmi
- InstanceType: m5ad.large # Nitro Instance Type
- Volumes:
- - Device: /dev/sdb # EBS Volume
- VolumeId: !ImportValue StatefulVolumeId
- BlockDeviceMappings:
- - DeviceName: /dev/sdh # Instance Store
- VirtualName: ephemeral0
- UserData:
- Fn::Base64: !Sub
- - |+
- #cloud-config
- write_files:
- - content: |
- devices:
- /dev/sdb:
- fs: ${FileSystem}
- mountPoint: /mnt/ebs
- mountOptions: ${MountOptions}
- user: ubuntu
- group: ubuntu
- permissions: 755
- label: stateful
- mode: healthcheck
- /dev/sdh:
- fs: ${FileSystem}
- mountPoint: /mnt/instance-store
- mountOptions: ${MountOptions}
- user: ubuntu
- group: ubuntu
- permissions: 755
- label: ephemeral
- mode: force
- path: /etc/ebs-bootstrap/config.yml
- bootcmd:
- - curl -L -o /tmp/ebs-bootstrap "${EbsBootstrapUrlPrefix}-$(uname -m)"
- - install -m755 /tmp/ebs-bootstrap /usr/local/sbin/ebs-bootstrap
- runcmd:
- - /usr/local/sbin/ebs-bootstrap
- mounts:
- - [ "LABEL=stateful", /mnt/ebs, ${FileSystem}, "${MountOptions}", "0", "2"]
- - FileSystem: ext4
- MountOptions: defaults,nofail,x-systemd.device-timeout=5
- EbsBootstrapUrlPrefix: https://github.com/reecetech/ebs-bootstrap/releases/latest/download/ebs-bootstrap-linux
-```
+From the perspective of a **sceptical** Platforms Engineer, you do not mind delegating the task of formatting and mounting ephemeral block devices to `ebs-bootstrap`. However, you personally draw the line on automation executing modifications to a stateful device, **without** the prior consent of a human. `ebs-bootstrap` empowers this Platform Engineer by allowing them to specify the execution mode, on a **device-by-device** basis: Instance Store (`force`) and EBS Volume (`healthcheck`)
+
+
+
+
-Assuming this is the very first launch, `ebs-bootstrap` would refuse to perform any modifications associated to the EBS device as it was assigned the `healthcheck` mode. However, we can temporarily override this behaviour with the `-mode=prompt` option. This allows the Platform Engineer to approve any suggested changes by `ebs-bootstrap`.
+> This CloudFormation template demonstrates the installation and configuration of `ebs-bootstrap` on an **Ubuntu Nitro EC2 Instance**. The instance has both an EBS and an Instance Store Volume attached, and the setup is performed using `cloud-init`.
+
+On the first launch, `ebs-bootstrap` would refuse to perform any modifications to the EBS volume as it was assigned the `healthcheck` mode. However, we can temporarily override this behaviour with the `-mode=prompt` option. This allows the Platform Engineer to approve any suggested changes by `ebs-bootstrap`.
```
-[~] sudo /usr/local/sbin/ebs-bootstrap -mode=prompt
+
+[~] sudo ebs-bootstrap -mode=prompt
🔵 /dev/nvme1n1: Detected Nitro-based AWS NVMe device => /dev/sdb
🔵 /dev/nvme2n1: Detected Nitro-based AWS NVMe device => /dev/sdh
🟠Formatting larger disks can take several seconds ⌛
@@ -169,35 +117,32 @@ LABEL=stateful /mnt/ebs ext4 defaults,nofail,x-systemd.device-timeout=5,comment=
### `systemd`
-A potential way of operating `ebs-bootstrap` is through a `systemd` service. This is so we can configure it as a `oneshot` service type that executes after the file system is ready and `clout-init.service` writes any config files to disk. The latter is essential as `ebs-bootstrap` consumes a config file that is located at `/etc/ebs-boostrap/config.yml` by default.
-
-`ExecStopPost=-...` can point towards a script that is executed when the `ebs-bootstrap` service exits on either success or failure. This is a suitable place to include logic to notify an individual that the configured devices failed their relevant healthchecks and the underlying application failed to launch in the process.
+One way to utilise ebs-bootstrap is by employing a **oneshot** `systemd` service. This approach allows us to activate `ebs-bootstrap` during system startup, guaranteeing that any EBS or Instance Store volumes are formatted and mounted whenever the system is rebooted.
```ini
[Unit]
-Description=EBS Bootstrap
-After=local-fs.target cloud-init.service
+Description=ebs-bootstrap
+After=local-fs.target cloud-init.service # Run after write_files module in cloud-init.service
[Service]
Type=oneshot
RemainAfterExit=true
-StandardInput=null
+StandardInput=null # Disables stdin to error on prompt
ExecStart=/usr/local/sbin/ebs-bootstrap
-PrivateMounts=no
-MountFlags=shared
-ExecStopPost=-/etc/ebs-bootstrap/post-hook.sh
+PrivateMounts=no # Prevents private mount namespaces
+MountFlags=shared # Shares mounts to other processes
[Install]
WantedBy=multi-user.target
```
-It is then possible to configure another `systemd` service to only start if the `ebs-bootstrap` service is successful. Certain databases support the ability to spread database chunks across multiple devices that need to be mounted to pre-defined directories with the correct ownership and permissions.
+It is then possible to configure another `systemd` service to **only** start if the `ebs-bootstrap` service is successful. Certain databases support the ability to spread database chunks across multiple block devices that need to be mounted to pre-defined directories with the correct ownership and permissions enforced.
-In this particular use-case, the database could be configured as a `systemd` service that relies on the `ebs-bootstrap.service` to succeed before attempting to start. This can be achieved by specifiying `ebs-boostrap.service` as a dependency in the `Requires=` and `After=` parameters.
+In this particular use-case, the database could be configured as a `systemd` service that relies on the `ebs-bootstrap.service` to succeed before attempting to start. This can be achieved by specifying `ebs-boostrap.service` as a dependency in the `Requires=` and `After=` parameters.
```ini
[Unit]
-Description=Example Database
+Description=postgres
Wants=network-online.target
Requires=ebs-bootstrap.service
After=network.target network-online.target ebs-bootstrap.service
diff --git a/assets/badges/cloudformation.svg b/assets/badges/cloudformation.svg
new file mode 100644
index 0000000..77f836a
--- /dev/null
+++ b/assets/badges/cloudformation.svg
@@ -0,0 +1 @@
+
diff --git a/assets/badges/github-wiki.svg b/assets/badges/github-wiki.svg
new file mode 100644
index 0000000..e05fa7d
--- /dev/null
+++ b/assets/badges/github-wiki.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/cloudformation.yml b/examples/cloudformation.yml
new file mode 100644
index 0000000..d6a7aa2
--- /dev/null
+++ b/examples/cloudformation.yml
@@ -0,0 +1,131 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Description: |
+ Deploys an EC2 Instance with an EBS and an Instance Store volume. To
+ reduce cost of operating this example, we use Graviton-supported Instance
+ types and AMI
+
+Parameters:
+ KeyName:
+ Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
+ Type: AWS::EC2::KeyPair::KeyName
+ ConstraintDescription: Must be the name of an existing EC2 KeyPair.
+ AvailabilityZone:
+ Type: AWS::EC2::AvailabilityZone::Name
+ Description: Availability Zone where EBS Volume will be created
+ SubnetId:
+ Type: AWS::EC2::Subnet::Id
+ Description: The Subnet ID where the EC2 instance will be launched.
+ VpcId:
+ Type: AWS::EC2::VPC::Id
+ Description: The VPC ID where the EC2 instance will be launched.
+ NitroInstanceType:
+ Type: String
+ Default: c6gd.medium
+ Description: Instance Type
+ ConstraintDescription: |
+ For this example, must be a Nitro Instance Type with at least one Instance Store volume
+ IngressSshCidr:
+ Description: The IP address range that can be used to SSH to the EC2 instances
+ Type: String
+ MinLength: 9
+ MaxLength: 18
+ Default: 0.0.0.0/0
+ AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
+ ConstraintDescription: Must be a valid IP CIDR range of the form x.x.x.x/x.
+ LatestUbuntuAmi:
+ Type: AWS::SSM::Parameter::Value
+ Default: /aws/service/canonical/ubuntu/server/20.04/stable/current/arm64/hvm/ebs-gp2/ami-id
+
+Resources:
+ SecurityGroup:
+ Type: AWS::EC2::SecurityGroup
+ Properties:
+ GroupDescription: Security Group for EC2 instance
+ VpcId: !Ref VpcId
+ SecurityGroupIngress:
+ - CidrIp: !Ref IngressSshCidr
+ IpProtocol: tcp
+ FromPort: 22
+ ToPort: 22
+ EbsVolume:
+ Type: AWS::EC2::Volume
+ Properties:
+ Size: 10
+ AvailabilityZone: !Ref AvailabilityZone
+ DeletionPolicy: Delete
+ Instance:
+ Type: AWS::EC2::Instance
+ Properties:
+ KeyName: !Ref KeyName
+ ImageId: !Ref LatestUbuntuAmi
+ InstanceType: !Ref NitroInstanceType
+ SecurityGroupIds:
+ - !Ref SecurityGroup
+ SubnetId: !Ref SubnetId
+ Volumes:
+ - Device: "/dev/sdb" # EBS
+ VolumeId: !Ref EbsVolume
+ BlockDeviceMappings:
+ - DeviceName: "/dev/sdh"
+ VirtualName: "ephemeral0" # Instance Store volume
+ UserData:
+ Fn::Base64: !Sub
+ - |+
+ #cloud-config
+ write_files:
+ - content: |
+ devices:
+ /dev/sdb:
+ fs: ${FileSystem}
+ mountPoint: /mnt/ebs
+ mountOptions: ${MountOptions}
+ user: ubuntu
+ group: ubuntu
+ permissions: 755
+ label: stateful
+ mode: healthcheck
+ /dev/sdh:
+ fs: ${FileSystem}
+ mountPoint: /mnt/instance-store
+ mountOptions: ${MountOptions}
+ user: ubuntu
+ group: ubuntu
+ permissions: 755
+ label: ephemeral
+ mode: force
+ path: /etc/ebs-bootstrap/config.yml
+ - content: |
+ [Unit]
+ Description=ebs-bootstrap
+ After=local-fs.target cloud-init.service
+
+ [Service]
+ Type=oneshot
+ RemainAfterExit=true
+ StandardInput=null
+ ExecStart=/usr/local/sbin/ebs-bootstrap
+ PrivateMounts=no
+ MountFlags=shared
+
+ [Install]
+ WantedBy=multi-user.target
+ path: /etc/systemd/system/ebs-bootstrap.service
+ bootcmd:
+ - curl -L -o /tmp/ebs-bootstrap "${EbsBootstrapUrlPrefix}-$(uname -m)"
+ - install -m755 /tmp/ebs-bootstrap /usr/local/sbin/ebs-bootstrap
+ runcmd:
+ - systemctl daemon-reload
+ - systemctl enable ebs-bootstrap --now
+ mounts:
+ - [ "LABEL=stateful", /mnt/ebs, ${FileSystem}, "${MountOptions}", "0", "2"]
+ - FileSystem: ext4
+ MountOptions: defaults,nofail,x-systemd.device-timeout=5
+ EbsBootstrapUrlPrefix: https://github.com/reecetech/ebs-bootstrap/releases/latest/download/ebs-bootstrap-linux
+
+Outputs:
+ InstanceId:
+ Description: Instance Id of the newly created EC2 instance
+ Value: !Ref Instance
+ PrivateIP:
+ Description: Private IP address of the newly created EC2 instance
+ Value: !GetAtt [Instance, PrivateIp]
diff --git a/examples/systemd.service b/examples/systemd.service
new file mode 100644
index 0000000..5c89c5d
--- /dev/null
+++ b/examples/systemd.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=ebs-bootstrap
+After=local-fs.target cloud-init.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=true
+StandardInput=null
+ExecStart=/usr/local/sbin/ebs-bootstrap
+PrivateMounts=no
+MountFlags=shared
+
+[Install]
+WantedBy=multi-user.target