124 stories
1 follower

Here's Where That Ram Ad Really Got Martin Luther King Jr. Wrong

1 Share

Ram debuted an ad at the Super Bowl last night featuring the appropriated words of the Reverend Dr. Martin Luther King Jr. If you haven’t seen it, it was bad and dumb, and has been derided pretty much across the board. But it’s not just the use of King’s words to sell trucks that got it wrong—it’s what the rest of…


Read the whole story
40 days ago
Share this story

Dynamic Inventory: Past, Present & Future

1 Share

In Red Hat Ansible Engine 2.4, we made some changes to how inventory works. We introduced a new cli tool, and added an inventory plugin type.

The goal of this plugin type, was well, to make Ansible Engine even more pluggable. All kidding aside, we wanted to provide Ansible Engine content authors and Ansible Engine users a new way to visualize their target inventory.  Using the ansible-inventory command,  the targeted inventory will be listed with the details of the hosts in that inventory, and the hosts groups.

For example:

[thaumos@ecb51a545078 /]# ansible-inventory -i ~/Development/playbooks/inventory/prod.aws_ec2.yml --list
    "_meta": {
        "hostvars": {
            "ec2-5x-xx-x-xxx.us-west-2.compute.amazonaws.com": {
                "AmiLaunchIndex": 2,
                "Architecture": "x86_64",
                "BlockDeviceMappings": [
                        "DeviceName": "/dev/sda1",
                        "Ebs": {
                            "AttachTime": "2017-12-13T15:40:19+00:00",
                            "DeleteOnTermination": false,
                            "Status": "attached",
                            "VolumeId": "vol-0514xxx"
                "ClientToken": "",
                "EbsOptimized": false,
                "Hypervisor": "xen",
                "ImageId": "ami-0c2aba6c",
                "InstanceId": "i-009xxxx3",
                "InstanceType": "t2.micro",
                "KeyName": "blogKey",
                "LaunchTime": "2017-12-13T15:40:18+00:00",
                "Monitoring": {
                    "State": "disabled"
                "NetworkInterfaces": [
                        "Association": {
                            "IpOwnerId": "amazon",
                            "PublicDnsName": "ec2-5x-xx-x-xxx.us-west-2.compute.amazonaws.com",
                            "PublicIp": "5x.xx.x.xxx"
                        "Attachment": {
                            "AttachTime": "2017-12-13T15:40:18+00:00",
                            "AttachmentId": "eni-attach-97c4xxxx",
                            "DeleteOnTermination": true,
                            "DeviceIndex": 0,
                            "Status": "attached"
                        "Description": "",
                        "Groups": [
                                "GroupId": "sg-e63xxxxd",
                                "GroupName": "blogGroup"
                        "Ipv6Addresses": [],
                        "MacAddress": "02:50:99:0b:e8:e8",
                        "NetworkInterfaceId": "eni-eaxxxxxx",
                        "OwnerId": "xxxxxxxx",
                        "PrivateDnsName": "ip-1xx-xx-xx-x.us-west-2.compute.internal",
                        "PrivateIpAddress": "1xx.xx.xx.x",
                        "PrivateIpAddresses": [
                                "Association": {
                                    "IpOwnerId": "amazon",
                                    "PublicDnsName": "ec2-5x-xx-x-xxx.us-west-2.compute.amazonaws.com",
                                    "PublicIp": "52.xx.x.xxx"
                                "Primary": true,
                                "PrivateDnsName": "ip-1xx-xx-xx-x.us-west-2.compute.internal",
                                "PrivateIpAddress": "1xx.xx.xx.x"
                        "SourceDestCheck": true,
                        "Status": "in-use",
                        "SubnetId": "subnet-1xxx279",
                        "VpcId": "vpc-4cxxxx29"
                "Placement": {
                    "AvailabilityZone": "us-west-2a",
                    "GroupName": "",
                    "Tenancy": "default"
                "PrivateDnsName": "ip-1xx-xx-xx-x.us-west-2.compute.internal",
                "PrivateIpAddress": "1xx.xx.x.x",
                "ProductCodes": [],
                "PublicDnsName": "ec2-5x-xx-x-xxx.us-west-2.compute.amazonaws.com",
                "PublicIpAddress": "5x.xx.x.xxx",
                "RootDeviceName": "/dev/sda1",
                "RootDeviceType": "ebs",
                "SecurityGroups": [
                        "GroupId": "sg-e6xxxxxx",
                        "GroupName": "blogGroup"
                "SourceDestCheck": true,
                "State": {
                    "Code": 16,
                    "Name": "running"
                "StateTransitionReason": "",
                "SubnetId": "subnet-1cxxxxxx",
                "Tags": [
                        "Key": "env",
                        "Value": "Production"
                        "Key": "Name",
                        "Value": "blogKey"
                "VirtualizationType": "hvm",
                "VpcId": "vpc-4cexxxxx"
    "all": {
        "children": [
    "aws_ec2_instance_type_t2_micro": {
        "hosts": [
    "aws_ec2_tag_value_blogger": {
        "hosts": [
    "ungrouped": {}
Another nifty thing the tool does is show a tree or graph of what the inventory looks like:
[thaumos@ecb51a545078 /]# ansible-inventory -i ~/Development/playbooks/inventory/prod.aws_ec2.yml --graph
  |  |--ec2-5x-xx-x-xxx.us-west-2.compute.amazonaws.com
  |  |--ec2-5x-xx-x-xxx.us-west-2.compute.amazonaws.com

All of this data is being provided by our new AWS EC2 inventory plugin!  Inventory plugins are a much simpler interface for Ansible Engine content providers to interact with the underlying inventory components. This inventory plugin will be provided as a tech-preview. Please provide feedback on it!

Most inventory plugins utilize simple yaml based configuration files to activate the plugin[1] and fine tune the data collected.  Here's an example:

    plugin: aws_ec2
    boto_profile: default
    regions: # populate inventory with instances in these regions
      - us-west-2
    # makes a group for instances that have the tag values 'thaumos' and 't2.micro' instance type.
      - tag-value=thaumos
      - instance-type=t2.micro
      tag:Name: blogger
      tag:env: Production
      instance-state-name: running
    strict_permissions: False

These plugins also have access to the inventory cache that is being built in Ansible Engine 2.5, also in tech preview.  This inventory cache allows for users to combine the powers, so to speak, of other inventory plugins.  For instance, imagine using any of the cloud inventory plugins to pull data about the instances and the constructed inventory plugin and jinja to build groups as decided by the user!  This approach is much more flexible than before; where a content developer would have to build grouping into the dynamic inventory script itself.

I hope the information in this blog post is a great teaser to up and coming features.  I plan on doing little teasers like these more often as we have new stuff coming in Ansible Engine.  These posts will also coincide with a webinar.  The webinar for this blog post can be found here!

Continue Automating all the things!

[1]: Default behaviour in configuration.  Remove 'auto' from INVENTORY_ENABLED in ansible config to stop auto-loading of inventory plugins.


Read the whole story
47 days ago
Share this story

Terraforming 1Password

1 Share

A few days ago I posted this tweet:

The tweet generated quite a bit of interest from people running or managing their own services and I thought I would share some of the cool things we are working on.

This post will go into technical details and I apologize in advance if I explain things too quickly. I tried to make up for this by including some pretty pictures but most of them ended up being code snippets. 🙂

1Password and AWS

1Password is hosted by Amazon Web Services (AWS). We’ve been using AWS for several years now and it is amazing how easy it was to scale our service from zero users three years ago to several million happy customers today.

AWS has many geographical regions. Each region consists of multiple independent data centres located closely together. We are currently using three regions:

  • N. Virginia, USA us-east-1
  • Montreal, Canada ca-central-1
  • Frankfurt, Germany eu-central-1

In each region we have four environments running 1Password:

  • production
  • staging
  • testing
  • development

If you are counting, that’s 12 environments across three regions, including three production environments: 1password.com, 1password.ca, and 1password.eu.

Every 1Password environment is more or less identical and includes these components:

  • Virtual Private Cloud
  • Amazon Aurora database cluster
  • Caching (Redis) clusters
  • Subnets
  • Routing tables
  • Security roles
  • IAM permissions
  • Auto scaling groups
  • Elastic Compute Cloud (EC2) instances
  • Elastic Load Balancers (ELB)
  • Route53 DNS (both internal and external)
  • Amazon S3 buckets
  • CloudFront distributions
  • Key Management System (KMS)

Here is a simplified diagram:


As you can see, there are many components that work together to provide 1Password service. One of the reasons it is so complex is the need for high availability. Most of the components are deployed as a cluster to make sure there are at least two of each: database, cache, server instance, and so on.

Furthermore, every AWS region has at least two data centres that are also known as Availability Zones (AZs) – you can see them in blue in the diagram above. Every AZ has its own independent power and network connections. For example, Canadian region ca-central-1 has two data centres: ca-central-1a and ca-central-2a.

If we deployed all 1Password components into just a single Availability Zone, then we would not be able to achieve high availability because a single problem in the data centre would take 1Password offline. This is why when 1Password services are deployed in a region, we make sure that every component has at least one backup in the neighbouring data centre. This helps to keep 1Password running even when there’s a problem in one of the data centres.

Infrastructure as Code

It would be very difficult and error-prone to manually deploy and maintain 12 environments, especially when you consider that each environment consists of at least 50 individual components.

This is why so many companies today switched from updating their infrastructure manually and embraced Infrastructure as Code. With Infrastructure as Code, the hardware becomes software and can take advantage of all software development best practices. When we apply these practices to infrastructure, every server, every database, every open network port can be written in code, committed to GitHub, peer-reviewed, and then deployed and updated as many times as necessary.

For AWS customers, there are two major languages that could be used to describe and maintain the infrastructure:

CloudFormation is a great option for many AWS customers and we successfully used it to deploy 1Password environments for over two years. At the same time we wanted to move to Terraform as our main infrastructure tool for several reasons:

  • Terraform has a simpler and more powerful language (HCL) that makes it easier to write and review code.
  • Terraform has the concept of resource providers that allows us to manage resources outside of Amazon Web Services, including services like DataDog and PagerDuty, which we rely on internally.
  • Terraform is completely open source and that makes it easier to understand and troubleshoot.
  • We are already using Terraform for smaller web apps at AgileBits and it makes sense to standardize on a single tool.

Compared to the JSON or YAML files used by CloudFormation, Terraform HCL is both a more powerful and a more readable language. Here is a small example with a snippet that defines a subnet for the application servers. As you can see, the Terraform code a quarter of the size, more readable, and easier to understand.


"B5AppSubnet1": {
    "Type": "AWS::EC2::Subnet",
    "Properties": {
        "CidrBlock": { "Fn::Select" : ["0", { "Fn::FindInMap" : [ "SubnetCidr", { "Ref" : "Env" }, "b5app"] }] },
        "AvailabilityZone": { "Fn::Select" : [ "0", { "Fn::GetAZs" : "" } ]},
        "VpcId": { "Ref": "Vpc" },
        "Tags": [
            { "Key" : "Application", "Value" : "B5" },
            { "Key" : "env", "Value": { "Ref" : "Env" } },
            { "Key" : "Name", "Value": { "Fn::Join" : ["-", [ {"Ref" : "Env"}, "b5", "b5app-subnet1"]] } }

"B5AppSubnet2": {
    "Type": "AWS::EC2::Subnet",
    "Properties": {
        "CidrBlock": { "Fn::Select" : ["1", { "Fn::FindInMap" : [ "SubnetCidr", { "Ref" : "Env" }, "b5app"] }] },
        "AvailabilityZone": { "Fn::Select" : [ "1", { "Fn::GetAZs" : "" } ]},
        "VpcId": { "Ref": "Vpc" },
        "Tags": [
            { "Key" : "Application", "Value" : "B5" },
            { "Key" : "env", "Value": { "Ref" : "Env" } },
            { "Key" : "Name", "Value": { "Fn::Join" : ["-", [ {"Ref" : "Env"}, "b5", "b5app-subnet2"]] } }

"B5AppSubnet3": {
    "Type": "AWS::EC2::Subnet",
    "Properties": {
        "CidrBlock": { "Fn::Select" : ["2", { "Fn::FindInMap" : [ "SubnetCidr", { "Ref" : "Env" }, "b5app"] }] },
        "AvailabilityZone": { "Fn::Select" : [ "2", { "Fn::GetAZs" : "" } ]},
        "VpcId": { "Ref": "Vpc" },
        "Tags": [
            { "Key" : "Application", "Value" : "B5" },
            { "Key" : "env", "Value": { "Ref" : "Env" } },
            { "Key" : "Name", "Value": { "Fn::Join" : ["-", [ {"Ref" : "Env"}, "b5", "b5app-subnet3"]] } }


resource "aws_subnet" "b5app" {
  count             = "${length(var.subnet_cidr["b5app"])}"
  vpc_id            = "${aws_vpc.b5.id}"
  cidr_block        = "${element(var.subnet_cidr["b5app"],count.index)}"
  availability_zone = "${var.az[count.index]}"

  tags {
    Application = "B5"
    env         = "${var.env}"
    type        = "${var.type}"
    Name        = "${var.env}-b5-b5app-subnet-${count.index}"

Terraform has another gem of a feature that we rely on: terraform plan. It allows us to visualize the changes that will happen to the environment without performing them.

For example, here is what would happen if we change the server instance size from t2.medium to t2.large.

Terraform Plan Output

# Terraform code changes
# variable "instance_type" {
#    type        = "string"
# -  default     = "t2.medium"
# +  default     = "t2.large"
#  }

$ terraform plan 
Refreshing Terraform state in-memory prior to plan...


An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

-/+ module.b5site.aws_autoscaling_group.asg (new resource required)
      id:                                 "B5Site-prd-lc20180123194347404900000001-asg" =>  (forces new resource)
      arn:                                "arn:aws:autoscaling:us-east-1:921352000000:autoScalingGroup:32b38032-56c6-40bf-8c57-409e9e4a264a:autoScalingGroupName/B5Site-prd-lc20180123194347404900000001-asg" => 
      default_cooldown:                   "300" => 
      desired_capacity:                   "2" => "2"
      force_delete:                       "false" => "false"
      health_check_grace_period:          "300" => "300"
      health_check_type:                  "ELB" => "ELB"
      launch_configuration:               "B5Site-prd-lc20180123194347404900000001" => "${aws_launch_configuration.lc.name}"
      load_balancers.#:                   "0" => 
      max_size:                           "3" => "3"
      metrics_granularity:                "1Minute" => "1Minute"
      min_size:                           "2" => "2"
      name:                               "B5Site-prd-lc20180123194347404900000001-asg" => "${aws_launch_configuration.lc.name}-asg" (forces new resource)
      protect_from_scale_in:              "false" => "false"
      tag.#:                              "4" => "4"
      tag.1402295282.key:                 "Application" => "Application"
      tag.1402295282.propagate_at_launch: "true" => "true"
      tag.1402295282.value:               "B5Site" => "B5Site"
      tag.1776938011.key:                 "env" => "env"
      tag.1776938011.propagate_at_launch: "true" => "true"
      tag.1776938011.value:               "prd" => "prd"
      tag.3218409424.key:                 "type" => "type"
      tag.3218409424.propagate_at_launch: "true" => "true"
      tag.3218409424.value:               "production" => "production"
      tag.4034324257.key:                 "Name" => "Name"
      tag.4034324257.propagate_at_launch: "true" => "true"
      tag.4034324257.value:               "prd-B5Site" => "prd-B5Site"
      target_group_arns.#:                "2" => "2"
      target_group_arns.2352758522:       "arn:aws:elasticloadbalancing:us-east-1:921352000000:targetgroup/prd-B5Site-8080-tg/33ceeac3a6f8b53e" => "arn:aws:elasticloadbalancing:us-east-1:921352000000:targetgroup/prd-B5Site-8080-tg/33ceeac3a6f8b53e"
      target_group_arns.3576894107:       "arn:aws:elasticloadbalancing:us-east-1:921352000000:targetgroup/prd-B5Site-80-tg/457e9651ad8f1af4" => "arn:aws:elasticloadbalancing:us-east-1:921352000000:targetgroup/prd-B5Site-80-tg/457e9651ad8f1af4"
      vpc_zone_identifier.#:              "2" => "2"
      vpc_zone_identifier.2325591805:     "subnet-d87c3dbc" => "subnet-d87c3dbc"
      vpc_zone_identifier.3439339683:     "subnet-bfe16590" => "subnet-bfe16590"
      wait_for_capacity_timeout:          "10m" => "10m"

-/+ module.b5site.aws_launch_configuration.lc (new resource required)
      id:                                 "B5Site-prd-lc20180123194347404900000001" =>  (forces new resource)
      associate_public_ip_address:        "false" => "false"
      ebs_block_device.#:                 "0" => 
      ebs_optimized:                      "false" => 
      enable_monitoring:                  "true" => "true"
      iam_instance_profile:               "prd-B5Site-instance-profile" => "prd-B5Site-instance-profile"
      image_id:                           "ami-263d0b5c" => "ami-263d0b5c"
      instance_type:                      "t2.medium" => "t2.large" (forces new resource)
      key_name:                           "" => 
      name:                               "B5Site-prd-lc20180123194347404900000001" => 
      name_prefix:                        "B5Site-prd-lc" => "B5Site-prd-lc"
      root_block_device.#:                "0" => 
      security_groups.#:                  "1" => "1"
      security_groups.4230886263:         "sg-aca045d8" => "sg-aca045d8"
      user_data:                          "ff8281e17b9f63774c952f0cde4e77bdba35426d" => "ff8281e17b9f63774c952f0cde4e77bdba35426d"

Plan: 2 to add, 0 to change, 2 to destroy.

Overall, Terraform is a pleasure to work with and that makes a huge difference in our daily lives. DevOps people like to enjoy their lives too. 🙌

Migration from CloudFront to Terraform

It is possible to simply import the existing AWS infrastructure directly into Terraform but there are certain downsides to it. We found that naming conventions are quite different and that would make it more challenging to maintain our environments in the future. Also, a simple import would not allow us to use the new Terraform features. For example, instead of hard-coding the identifiers of Amazon Machine Images used for deployment we started using aws_ami to dynamically find the most recent image:


data "aws_ami" "bastion_ami" {
  most_recent = true
  filter {
    name   = "architecture"
    values = ["x86_64"]
  filter {
    name   = "name"
    values = ["bastion-*"]
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  name_regex = "bastion-.*"
  owners     = [92135000000]

It took us a couple weeks to write the code from scratch. After we had the same infrastructure described in Terraform, we recreated all non-production environments where downtime wasn’t an issue. This also allowed us to create a complete checklist of all the steps required to migrate the production environment.

Finally, on January 21, 2018, we completely recreated 1Password.com. We had to bring the service offline during the migration. Most of our customers were not affected by the downtime because the 1Password apps are designed to function even when the servers are down or when an Internet connection is not available. Unfortunately, our customers who needed to access the web interface during that time were unable to do so, and we apologize for the interruption. Most of the 2 hours and 39 minutes of downtime was related to data migration. The 1Password.com database is just under 1TB in size (not including documents and attachments) and it took almost two hours to complete the snapshot and restore operations.

We are excited to finally have all our development, test, staging, and production environments managed with Terraform. There are many new features and improvements we have planned for 1Password and it will be fun to review new infrastructure pull requests on GitHub!

I remember when we were starting out we hosted our very first server with 1&1. It would have taken weeks to rebuild the very simple environment there. The world has come a long way since we first launched 1Passwd 13 years ago. I am looking forward to what the next 13 years will bring! 😃


A few questions and suggestions about the migration came up on Twitter:

By “recreating” you mean building out a whole new VPC with Terraform? Couldn’t you build it then switch existing DNS over for much less down time?1

This is pretty much what we ended up doing. Most of the work was performed before the downtime. Then we updated the DNS records to point to the new VPC.

Couldn’t you’ve imported all online resources? Just wondering.2

That is certainly possible and it would have allowed us to avoid downtime. Unfortunately, it also requires manual mapping of all existing resources. Because of that, it’s hard to test and the chance of a human error is high – and we know humans are pretty bad at this. As a wise person on Twitter said: “If you can’t rebuild it, you can’t rebuild it“.

If you have any questions, let us know in the comments, or ask me (@roustem) and Tim (@stumyp), our Beardless Keeper of Keys and Grounds, on Twitter.

Read the whole story
51 days ago
Share this story

Apple buys original space drama TV series from 'Battlestar Galactica' creator

1 Share
Article Image

Ronald D. Moore, the brain behind the critically acclaimed remake of "Battlestar Galactica," will pen a new space drama for Apple, as the company continues its push into original TV content to compete with the likes of Netflix, Amazon and Hulu.
Read the whole story
92 days ago
Share this story

High/low dressing

1 Share

The biggest potential pitfall with tailored dressing is looking fussy.

Fussy is not sexy; it is not attractive. It is closely related to appearing ‘affected’ or ‘mannered’.

Looking relaxed in clothing, on the other hand, is very attractive. It lies at the core of terms such as sprezzatura, grace and elegance.

It is why Hardy Amies told us to forget all about our clothing, once we had put it on.

I would argue this is at the very core of dressing well as a man, and is the thing sartorial dressers most frequently get wrong.

Fortunately, there are many ways to achieve it.

The first is dressing more simply, or avoiding anything that you feel you need to fuss with. The second and easiest is just being at ease, but this usually comes over a long period of wearing the same things. And a third is deliberately having some aspects of your dress imperfect (sprezzatura).  

Here we will look at a fourth: mixing casual and formal elements together - sometimes called high/low dressing.

It is not the easiest way to avoid looking fussy or mannered; indeed it is easy to get wrong.

But it is perhaps one of the most stylish way.

One guiding principle for high/low dressing is to play with the accessories, not the core. So outerwear, not jackets; shirts, not trousers.

A second is to be aware there are grades of high and low, which should not be pushed too far apart. So a Barbour jacket with a casual suit, but not with black tie.

The further apart these two extremes are, the easier it is to get it wrong.


1 Outerwear

The easiest and by far the most popular way to add casual, or low elements to an outfit is with outerwear.

Examples of casual (and often cheaper) outerwear pieces that can work well are:

  • Waxed/hunting jackets (Barbour, on Jake below, often being good because many are long enough to cover the full length of the jacket)
  • Duffle coats (Gloverall’s Monty - above - being the classic, but there are lots of other options)
  • Tweed/raglan-sleeved country coats (Smarter, but still definitely more casual than a tailored overcoat)
  • Cotton army coats (Largely field jackets like the M-45, and at a stretch a fishtail parka)

It's easier to look casual and unfussy if the coat is a little beaten up, which leads to a lot of men buying them vintage.

If the fit can work on you, that’s fine, and certainly better than buying artificially aged versions from designer brands.

But be careful with the length. For example, I love my vintage M-45 (shown in the introduction) but my height means it is too short to wear over a tailored jacket.

The issue there is milder version of short gilets over jackets. This is certainly a look, and I can see why some people like it, but for me it stretches the high/low separation too far.


2 Shirts

Second easiest is the casual shirt. Two examples of this have been ubiquitous in recent years: the denim shirt and the polo shirt.

One extreme of the denim shirt is the thick, pearl-snap cowboy shirt (above). The other is the Everyday Denim shirt, which is closer to being a dress shirt that fades nicely.

Mostly it’s safer to have something in the middle - which is obviously denim, but still functions well under a jacket (above).

My advice here would be to never sacrifice fit points (eg long tails to tuck in, collar at a decent height) but feel free to play with the colours, washes and design details.

On the polo shirt, of course, my favourite is the two versions of the Friday Polo I’ve offered here on Permanent Style. But many others, particularly The Armoury (above), offer really nice versions to wear with tailoring.

It subverts the assumptions of tailoring in exactly the same way as denim, but if cut like a regular shirt, mostly just shows in the material and texture.


3 Accessories

Accessories are one of the easiest things to add an outfit, but don’t tend to make as dramatic difference as outerwear.

A beanie that sits close on the head and retains a clean look (above) can be nice with tailoring, and is a big contrast to the alternative of a fedora or trilby.

Caps sit somewhere in between.

Colourful scarves, such as those from Drake’s, Liverano, Rubinacci and others, are not so much more casual and ‘low’ as more fun. They’re colourful, more playful, and can soften tailoring in that way.

They can also be a little flamboyant though, and if anything I tend to prefer more muted scarves such as indigo dyes to achieve the same effect.

I also often wear, as shown at the top of this post, Hermes silk scarves with coats and knitwear.

If anything this is high/low the other way round: the fanciness of a silk scarf being brought down to earth by a wax jacket. 


4 Shoes

A difficult area, largely because guys want to wear trainers with everything and it rarely works.

I’ve covered this in detail in my posts on how to buy and how to wear trainers, but in summary:

  • For a trainer to work with tailoring it must mimic some aspects of a dress shoe. Specifically long, clean lines, plain colour and a simple design.
  • They are best worn with more casual tailoring. So a cotton suit rather than a worsted suit, and most often just smart trousers, without a tailored jacket.

Most of the time, the best way to use shoes to look more relaxed is to just wear them - so they get worn in, look much loved and a little beaten up


5 T-shirts

A T-shirt under a jacket is a favourite of fashionable types, but rarely works.

If you have anything but a short neck, it will be much less flattering than a collared shirt. Also not great for the jacket collar against the skin.

In general - although not as casual - a rollneck or polo-collar buttoned up to the neck will be more effective. 

If you do want to try it, go for a lightweight crewneck sweater underneath the jacket, rather than a T-shirt.

If it’s in cotton, it won’t be much warmer than a T-shirt, and it will make the neckline much smarter. John Smedley even does short-sleeved cotton knits in the summer.

Wearing a slim scarf underneath (as shown above) the jacket can help, as it will create a substitute collar at the neck, and follow the lapels of the jacket nicely.


If you want to try something along these lines, I recommend starting with outerwear.

Wear a sports jacket and flannels into a vintage store, and try various things over the top of your jacket, to see how you like the look.

And don’t be fooled by magazine shots. If you think someone looks good in a T-shirt and jacket, cover up their good-looking face and athletic body, then reconsider.

Photography: All Jamie Ferguson except silk scarf/D-43 and indigo scarf (both Drake's), white trainers (James Munro) and T-shirt (Gieves & Hawkes)

Read the whole story
101 days ago
Share this story

Something is wrong on the internet


Writer and artist James Bridle has noticed that something is wrong on the internet. Specifically, algorithmically chosen and produced content is taking over more and more of the internet, including what your young children are watching on YouTube.

Someone or something or some combination of people and things is using YouTube to systematically frighten, traumatise, and abuse children, automatically and at scale, and it forces me to question my own beliefs about the internet, at every level.

By his own admission, there doesn’t seem to be anything egregiously wrong or upsetting about many of the examples Bridle uses. I mean, have you read Grimm’s fairy tales? Some of them are really dark and/or weird, like Black Mirror for children. But the effect in the aggregate is huge, resulting in what he asserts is a system of abuse in which Google is complicit, a technology fueled by advertising and weaponized against its users:

The architecture they have built to extract the maximum revenue from online video is being hacked by persons unknown to abuse children, perhaps not even deliberately, but at a massive scale. I believe they have an absolute responsibility to deal with this, just as they have a responsibility to deal with the radicalisation of (mostly) young (mostly) men via extremist videos — of any political persuasion. They have so far showed absolutely no inclination to do this, which is in itself despicable. However, a huge part of my troubled response to this issue is that I have no idea how they can respond without shutting down the service itself, and most systems which resemble it. We have built a world which operates at scale, where human oversight is simply impossible, and no manner of inhuman oversight will counter most of the examples I’ve used in this essay. The asides I’ve kept in parentheses throughout, if expanded upon, would allow one with minimal effort to rewrite everything I’ve said, with very little effort, to be not about child abuse, but about white nationalism, about violent religious ideologies, about fake news, about climate denialism, about 9/11 conspiracies.

Tags: Google   James Bridle   YouTube
Read the whole story
130 days ago
Share this story
Next Page of Stories