Outside Looking In

Jan 3, 2020

For about half of my life, I’ve felt like an outsider looking in. As far as I can tell, this started back in middle school when my parents moved me from one school to another. In my previous school I’d been the popular kid and a teachers’ pet, so I naively took all that bluster and confidence with me to the new school. This ultimately culminated in a dressing-down by the class teacher with my classmates taking turns complaining about me. Rather unpleasant as far as experiences go, and the stain of shame stuck with me all the way to graduation.

Going to college helped me fit in with my peers, but the feeling of being an outsider returned after I graduated from college and joined the workforce. I was the youngest kid in the company I was working at, and working with middle-aged parents wasn’t exactly the most fun experience ever. In high school I’d felt inferior to my classmates, here I felt superior to my colleagues who had no hobbies or interests. In both cases, I didn’t see myself fitting in and subsequently felt misunderstood and alone. Part of this was a cultural clash - the path most self-respecting Indians followed in life was:

  1. Get pushed out a vagina
  2. Go to school and study
  3. Go to college and study
  4. Get a job
  5. Marry the person your parents picked for you and pop out a few kids
  6. Sacrifice the rest of your life so your kids can follow this algorithm

Unfortunately, I grew up reading books written by western authors about life in the west. While my peers were watching the sappy trash that Bollywood puts out at a regular cadence, I grew up with movies like The Pursuit of Happyness and Serendipity. As a result, I wanted a life where I could pursue my dreams. I wanted to find someone and fall madly in love rather than have a business-like marriage. Did I feel superior to everyone else around me? Yes, most definitely, and I’m not proud of it. But a part of me also envied the people around me. I sort of felt like Cipher from the Matrix. Having taken the red pill, wide awake to the reality around me and wishing like hell that I could go back to sleep and languish in ignorance.

The feeling of being an outsider came back stronger than ever when I moved to the states. I expected the opposite to happen - after all, this was the life I’d been pining for all along. It should’ve felt like I’d finally reached my destination. But all of my insecurities came crawling out of the woodwork - insecurity about my heavy Indian accent, my early baldness, even the color of my skin. I looked for help online, found some recommendations to work out and started lifting. Losing fat and gaining muscles turned out to be exactly what I needed - I shed some of my body image issues and became a tad more confident in public. Graduating and joining Amazon in Seattle helped out more - I was lucky enough to get into a team of friendly engineers who welcomed me warmly and helped me feel at home. Talking to a therapist helped me identify some of the negative self-talk I’d been indulging in and set me on a path of constantly expanding my comfort zone. Life became exciting again, and I felt like I finally belonged; not because my environment had changed, but because I had. I felt secure in my identity, and no longer felt the need to change myself to appease others.

Which brings us to the here and now, dear reader. A few weeks ago I had the privilege of being dumped rather abruptly and unceremoniously by someone I’m crazy about. She didn’t have a strong reason for breaking up with me, just that she didn’t feel “that spark”. And the lack of a strong reason for being dumped simply left me agonizing over everything I said and did, wondering which combination of actions led to the breakup - a downward spiral I was stuck in until a friend assured me that it wasn’t anything I’d done. An unexpected side-effect of being dumped in this fashion - by someone I did feel “that spark” for - is that the feeling of being an outsider has reared its ugly head once more. Looking back at the last paragraph, I suspect this is because I’d been thinking about what I could’ve done differently to prevent being dumped, and this feeling of “I’m not good enough” is somehow tied to the feeling of not belonging. The onset was rather unexpected and sudden (similar to the break-up I guess, which was also unexpected and sudden): one moment I was at a pub devouring a po’boy and chatting with a friend, the next I was looking around at a sea of perfectly happy faces - with perfect teeth, clear, white skin, brown hair and blue/green eyes - and feeling like something the cat had dragged in. The feeling was so palpable that part of me wanted to just get up and bolt from that place. Thankfully, calmer heads prevailed and the urge passed soon enough.

One of the last things my therapist said to me (she had a baby and decided to take a break from work) is “you deserve to be loved, same as everyone else”. It wasn’t the first time she’d said something to that effect, but it didn’t really resonate with me. What does that even mean? You “deserve” something if you’ve earned it in some way. One can deserve love in a particular relationship, I don’t think it’s possible to generically deserve love in a non-specific manner. Maybe it’s just a matter of semantics though; if she’d told me that I’m lovable, I probably would’ve burst into tears. Because I think that’s one of my major hang-ups: at particularly low points in life (like this one I guess) I believe that I am inherently unlovable.

Tree in the Woods

Sep 16, 2019

If you do a good deed and nobody knows, does it count?

I hate litter, and as a kid I even hated people who littered. The streets of India have a lot of trash on them, and I would go out of my way to pick up large pieces of trash and deposit them in trash cans. I wonder, is all the trash I picked up tallied in a ledger somewhere?

If you love someone and they don’t love you back, where does that energy go?

Until my late twenties, I spent a lot of time and energy loving people who didn’t love me back. Unlike the stereotypical emo protagonist, I didn’t harden my heart against the world. Instead, I now find out early if my feelings are reciprocated, and if not then I consciously bail out. I wonder though - all that hurt, all that disappointment, all that angst.. where did it go? Did it contribute to the entropy of the universe in some way?

When someone assumes ill intent on your part, do you teach them about Hanlon’s razor?

Recently I had the rather unpleasant experience of having a (former) friend call me names and accuse me of being high-and-mighty, all because he didn’t make concrete plans with me and was offended that I couldn’t fit his nebulous plans into my schedule. In the past, I might have tried to show him the error of his ways or protested my innocence. Instead, I opted to wish him a good life and went on my way. I did spend a couple of hours agonizing over it, but I know that he probably had some other built-up resentment that only bubbled up due to that one incident.

When a relationship ends, why does it leave a gaping wound?

My very first relationship ended amicably towards the end of May this year. It was a good experience overall, but what took me by surprise was the feeling of emptiness that stuck around for several weeks after. I’ve read about that feeling in books, seen it in media, but none of that prepared me for the reality of feeling something by its sheer absence. It’s like you go looking inside yourself for a part of you and discover - to your sheer horror - that where there was something but a moment ago, there is now nothing. Until that moment I had only known feelings - good and bad - characterized by their presence. This is the only feeling - and I don’t know what to name it - that is characterized simply by its absence.

If you think an ill thought and never act on it, are you still bad?

If I think someone’s stupid but do my utmost to treat them fairly and patiently despite that, do they feel my impression of them on some level? Surely some of what I thought or felt must escape the confines of my mind and manifest in the physical world.

When you wear your heart on your sleeve and nobody cares, what can you do?

I wish I had an answer for this. My therapist assured me that someday, someone will come along and think “Hey, this right here is exactly what I want!” but I’ve decided “Fuck that!”. Only a crazy person does the same thing over and over again while expecting different results, right? It’s time to do something different.

When you stare deep into the abyss, does it stare back at you?

Yes, yes it does. Which is why it’s important to not stare. Maybe just take a peek out of the corner of your eyes once in a while?

If a tree falls in the woods and nobody is around, does it make a sound?

I read this question somewhere as a kid, and of course as a kid I only thought about it in the literal way and went “Duh! Next question!”

Now, it feels deep. I met a girl recently who has this tattooed on her forearm: “Fully seen. Fully loved.” And I love that. That’s how I wanted to live my life when I was younger. I lost track of that somewhere along the way, but I’ve recaptured that feeling over the past year. But now I realize that I cannot be that way all the time. There are patterns of expected behavior coded into our genes and the deepest recesses of our brains that most of us are completely unaware of. And like the birds of paradise I must learn how to dance so that the rest can follow.

Every Once in a While

Jun 17, 2019

We get caught up in our daily lives.

Daily lives

Exercise. Bills. Friends. Commitments. The pursuit of happiness.

Pursuit of happiness

And slowly but surely, the world gets smaller.

Pursuit of happiness

And smaller.

Smaller 1

And smaller.

Smaller 2

And smaller.

Smaller 3

And it’s not as obvious as the pictures above. You’re busy living life after all. Pursuing the dream. Work hard today, and you will get everything your heart desires.. somewhere down the line. Isn’t that what the books and movies tell us? The rags to riches story. The guy or gal who works their ass off for a decade or two, starts their own business and retires happily. The fairy tales. The princess who kisses every frog she comes across until one turns into a prince.

Frog turns into prince

We believe that we must suffer in order to deserve a better life. That happiness only lies on the other side of pain. And so we lift our burdens, toss them over our shoulders and we trudge on. Over spikes and flames. Through storms and hail. Fighting demons. Convinced that happiness lies just on the other side.

Fighting demons

Or perhaps you convince yourself that this is all life has to offer, and that life is just about compromises and adjustments. There are no happy endings, no happy-ever-after. You find someone good enough and you try to make it work. Like two pieces of a puzzle that just don’t fit together, but maybe if you tried hard enough, you could get by?

Puzzle pieces that don't fit

You stop believing in true love, or rather you believe that perhaps that it’s simply not something you will experience. You tell yourself that it’s time to stop being childish, to grow up.

Time to put the toys away

One by one, your dreams die. One compromise at a time, you shape yourself to fit into the life that seems to have found you. And then you put a neat little bow on it and declare that you’re done. You’ve figured life out!

Person in a tiny gift box

Every once in a while, someone comes along. They knock on your box and ask you if you’re okay in there. If you’re unlucky or blind enough, you nonchalantly reply “I’m good, how are you?” and they move on with their lives. Sometimes they climb into your box and stay for a little while. The sex is great, but the box isn’t big enough for the both of you.

But sometimes - just sometimes - something clicks. Maybe it’s something in their voice. Maybe it’s something in their eyes. Maybe your inner child remembers what it feels like to dream. You poke your head out of the box, and suddenly the world feels a little bit bigger.

Person peeking out of box

You realize that you’ve been holding your breath all this while. You let it all out, take a fresh one in, and the scent of flowers fills your senses. The world gets a little bit bigger.

Person staring at flowers

Your hear chirps, look up and see birds in the sky. The world gets even bigger.

Person staring at birds

The sun’s shining bright and bathes you in its warm, welcoming embrace. The world gets bigger.

Person staring at the sun

And bigger.

The world is huge

And it’s not that the person you met suddenly made your world bigger. The world has always been the same size, you just forgot. And that person reminded you.

With today’s always-connected world, it’s ironic that many of us feel less connected than ever before. It’s easy to get caught up in the daily drama of right-versus-left, of political correctness, of feeling society’s pressure to fit in. It’s easy to feel like we’re under attack and to strike back at the offenders. Humans evolved in communities, the need to feel like we belong is hard-wired into our DNA. And most of us would rather have an imperfect fit than to not have one at all.

I’m an introvert, and I’ve felt this urge to belong all my life. And there are a lot more of me in this world than there are loud, obnoxious “athletic douchebags” as someone I met recently put it. They’re out there, they’re yearning to connect with people and most of them don’t know how. It look me a year of therapy to learn how to reach out to people, to learn how to be vulnerable and risk getting hurt in order to make a genuine connection.

We humans either consciously or unconsciously search for meaning in our lives. I believe there is meaning to be found in reaching out to people and making their lives better in some way - small or great. But for any relationship to be formed, someone has to make the first move. When two introverts meet, both assume that they’re imposing on the other. Neither makes the first move and both leave convinced that they somehow let the other person down. Take the first step. I know it’s hard - I struggle with it every day. Just reach out and comfort someone in need. Let them know that you care. Become vulnerable and share a bit of your heart with them. People will surprise you.

Static Website With Hugo, AWS and Cloudflare

May 26, 2019

After writing my previous post about cleaning up my Continuous Deployment solution for deploying this site, I decided to experiment with AWS’s CodePipeline to set up my own home-grown pipeline to build and deploy the site instead of relying on CodeShip.

Infrastructure setup

For all its features, AWS doesn’t make it easy to set up and tweak things in a secure fashion. The recommended way of creating AWS resources is by using STS, IAM Roles and Policies to set up permissions in the most restrictive way possible. But that approach makes it really hard to iteratively create something when you aren’t quite sure about what you need to create and how all the parts are going to fit together. And then once you’re done setting everything up, you tend to lose track of all the little bits and pieces you created along the way that maybe didn’t end up fitting into the final product.

Enter Terraform. You create a few config files specifying all the resources you need and terraform goes and creates them for you. It keeps track of everything that it created, so making incremental changes easy. And if you really mess things up or the project doesn’t work out, you can run one command to destroy every single resource that was created.

So, I used a few blog posts (several turn up when you search for “s3 static website terraform github” on your favorite search engine) and a few existing terraform modules as a reference to set up a Terraform configuration that spins up an AWS CodePipeline which:

  1. Uses Github webhooks to listen for commits pushed to my blog’s (private) repository
  2. Uses AWS CodeBuild with a golang:1.12 base image to build the site. In my buildspec.yml I put commands to go get Hugo as the INSTALL step, ran hugo -v as the build command and then.. nothing. I’ll get back to that ominous “nothing” shortly.
  3. Uses Amazon S3 as a Deployment Provider in the Deploy step. More details here.

Everything seemed fine. I ran into a couple of permissions issues that turned out to be related to a misconfiguration of the encryption_key field in Terraform. However, I ran into a big hurdle. The last step for deploying to S3 would just fail with an extremely unhelpful error: InternalError: Error reference code: blah blah blah (the blah’s are mine). With no other information to go on, I created a post on the AWS forums and destroyed all Terraform assets a couple of days later when I hadn’t received a response on my post. But then I happily stumbled across a random buildspec.yml and saw that it had an artifacts section that listed a bunch of files. So I took a look at the reference for buildspec and sure enough, here’s what it says:

artifacts: Optional sequence. Represents information about where CodeBuild can find the build output and how CodeBuild prepares it for uploading to the Amazon S3 output bucket.

No shit, sherlock. Couldn’t you have told me that the deployment step couldn’t find any artifacts to upload instead of the useless InternalError? Anyway, I added an artifacts section to my buildspec, and the pipeline turned green! It was pushing the generated static files to my final destination bucket.

Gotta go fast!

Just one small issue at this point. Downloading hugo for each build took its own sweet time, in the order of a couple of minutes. Which isn’t a big issue when it comes to getting a blog post out, but being an engineer I prefer faster over slower (with some non-software exceptions of course). So I did some searching and came across this EXCELLENT post about creating custom docker images, storing them in AWS ECR and using them in your CodeBuild step instead of creating a new one each time (which is what the INSTALL step essentially does, it creates a base image and then modifies it each time). So I created a custom docker image using a simple Dockerfile that downloads and installs hugo. That made my entire CodeBuild step go from a few minutes to ~16 seconds.

Size is everything

…and dont’ let anyone tell you otherwise.

Despite using golang:1.12-alpine as the base image, the resulting docker image was still pretty big because it had all the Hugo source, Go source and build artifacts. Enter Docker multi-stage builds! This features lets you create one image that produces some build artifacts that can then be sent as input to a second image, and the resulting image is just the SECOND one, with none of the intermediate crap from the first one! Here’s what my Dockerfile looks like now:

FROM golang:1.12-alpine as builder

RUN apk add --no-cache git
RUN go get -v github.com/spf13/hugo

FROM alpine:latest
WORKDIR /go/bin
COPY --from=builder /go/bin/hugo .
ENV PATH=$PATH:/go/bin

Pretty self-explanatory, but the tl;dr version is that it copies the built Hugo binary from the first image to /go/bin/hugo and adds /go/bin to the PATH.

Free HTTPS and CDN

Cloudflare is awesome. I discovered a while ago that they offer a free CDN (content delivery network) and free DDOS protection and configured the DNS on my hostname provider at the time to use Cloudflare’s nameservers. When I first started this porting effort, I set up a CDN using AWS Cloudfront with HTTPS but quickly got overwhelmed. AWS’s pricing is pretty flexible, but the large number of tables talking about in-region and cross-region data transfers made it hard for me to figure out how much the whole shebang would cost me, especially given that my website doesn’t really get a lot of traffic as far as I know. It would probably still have been only pennies at the end, but why spend money if you don’t need to? In addition to the features listed above, Cloudflare also has a nice analytics dashboard, so I wouldn’t need to set up some sort of third-party analytics like Google Analytics. Additionally, Terraform has a Cloudflare provider. So instead of making an AWS-only solution, I tore down the Cloudfront resources and decided to use Cloudflare for CDN, DDOS protection and HTTPS everywhere. Didn’t have to do a lot to get it up and running, just had to use their API to fetch all my DNS records, import them into Terraform resources and then manually add zone settings overrides for other miscellaneous settings. The Cloudflare configuration in Terraform isn’t quite as neat and structured as the one for AWS, but it gets the job done.

Free for all

After putting so much effort into this solution, I wanted to make it available to others in an easy-to-use fashion. ECR doesn’t support public images that can be shared with others at the moment and I didn’t want users to have to first manually build an image and upload it to ECR before terraforming everything else. Fortunately, CodeBuild does support pulling images from Docker Hub so I uploaded my build image there under the name hugo-alpine and configured CodeBuild to use that instead of my ECR one. I moved all of my terraform configuration to a module with configurable variables for secrets and other user-specific values (like Github username, repo, etc). Terraform unfortunately doesn’t really work quite right if modules define their own providers, so the user needs to configure every provider themselves in order to use my module, but I’m mostly happy with the result. The final module is available here: https://github.com/ameyp/terraform-aws-cloudflare-static. I hope it works for you. Issues are welcome, as are pull requests!

A Brand New Git Repo

Apr 28, 2019

I remembered recently that this blog has been sitting around idle for a while. I figured that the continuous deployment solution I’d set up (CodeShip + Amazon S3) might’ve died by now (well, the CodeShip part anyway) but no, it’s still around. Those folks seem to be going strong, much to my surprised and delight.

However, a lot has changed in the past two years. For one, Github now supports unlimited private repositories with a free account. I had originally hosted the code (I use Hugo) on BitBucket because back then they had support for private repos and Github didn’t. However, all of my other repos are on Github, and since Github now supports private repos for free too, I figured that I might as well move this thing over too.

This was slightly complicated by the fact that CodeShip doesn’t allow you to change the backend used for one of their pipelines. You can switch from one BitBucket repo to another, or from one Github repo to another, but not from BitBucket to Github or vice versa. So, I cloned the repo locally, created a new one on Github, added that as a remote, duplicated my pipeline and pushed, and it worked! Of course, I also cleaned up some of the backend mess I had made the first time around. For instance, I had just straight up given CodeShip access to my main AWS account’s Access and Secret keys. Now, I have a custom policy that only grants write access to the one bucket it needs, and CodeShip has the keys to an IAM role with solely that policy attached. Much cleaner (and much, much safer!).

Some things changed on the Hugo side of things too, such as one function being removed and another being on the deprecation path, fixed those nits too.