| @@ -9,4 +9,6 @@ Desktop.ini | |||
| $RECYCLE.BIN/ | |||
| # OSX | |||
| .DS_Store | |||
| .DS_Store | |||
| .vscode | |||
| @@ -1,6 +1,6 @@ | |||
| dark-mode-toggle { | |||
| --dark-mode-toggle-dark-icon: url("/wp-content/moon.png"); | |||
| --dark-mode-toggle-dark-icon: url("/wp-content/moon.png"); | |||
| --dark-mode-toggle-dark-icon: url("/wp-content/sun.png"); | |||
| --dark-mode-toggle-light-icon: url("/wp-content/moon.png"); | |||
| } | |||
| body.light { | |||
| @@ -39,10 +39,18 @@ nav a { | |||
| color: #422eff; | |||
| border-bottom: 1px solid #00ff9c; | |||
| } | |||
| .dark a { | |||
| color: rgb(82, 174, 255); | |||
| border-bottom: 1px solid rgb(0, 204, 125); | |||
| } | |||
| .light a:hover { | |||
| color: #000; | |||
| background-color: #00ff9c; | |||
| } | |||
| .dark a:hover { | |||
| color: #333; | |||
| background-color: #00ff9c; | |||
| } | |||
| .muted, .help-block { | |||
| opacity: 0.70; | |||
| } | |||
| @@ -44,8 +44,13 @@ footnoteReturnLinkContents = "↩" # Provides a nicer footnote return link | |||
| name = "Blog" | |||
| identifier = "blog" | |||
| url = "/blog" | |||
| weight = 0 | |||
| weight = 2 | |||
| [[menu.main]] | |||
| name = "About" | |||
| identifier = "about" | |||
| url = "/about" | |||
| weight = 3 | |||
| [[menu.utility]] | |||
| name = "@rhnvrm" | |||
| @@ -0,0 +1,35 @@ | |||
| ## About | |||
| ### Work | |||
| I’m currently working as a Software Developer at | |||
| <a class="no-underline text-grey-dark" href="https://zerodha.com/products">Zerodha Tech</a> | |||
| where I am writing Golang, Python and a bit of Javascript to | |||
| build fintech products used at scale everyday. | |||
| Before Zerodha, I interned with Dell Technologies as a | |||
| Software Engineering Intern and graduated in the Summer of 2018 from | |||
| Shiv Nadar University, Dadri, India. | |||
| At Dell, I was part of a team that was building a | |||
| new end-to-end microservice based product using Golang (and Python) to solve an | |||
| invoice-to-order matching problem which had an effect of increasing | |||
| the cash flows for Dell and customer facing invoice accuracy | |||
| via last mile automation. | |||
| I have | |||
| also worked remotely during my participation in Google Summer | |||
| of Code in 2016 and contributed to the Open Source Apache | |||
| Allura Project that powers SourceForge.com. | |||
| Out of interest and curiosity, I have (little) experience with | |||
| Machine Learning and AI through my pursuit of a Machine Learning | |||
| Nanodegree which I earned through a MOOC curated by Udacity | |||
| which I undertook in the summer of 2017. | |||
| ### Personal | |||
| I am from New Delhi, India and am currently | |||
| based in Bengaluru, India. I write code for a living, | |||
| and often write code as a hobby, or to automate the | |||
| little things. You might find me lurking on online | |||
| message boards, online games and IRC as rhnvrm (an alias I took | |||
| long ago). | |||
| @@ -3,6 +3,7 @@ title = "Facebook Birthday List to ICS file" | |||
| date = 2019-10-11T01:03:03+05:30 | |||
| draft = false | |||
| categories = ["notes"] | |||
| tags = ["digital wellbeing", "python"] | |||
| type = "post" | |||
| url = "blog/2019/10/10/facebook-birthday" | |||
| author = "Rohan Verma" | |||
| @@ -3,6 +3,7 @@ title = "PaisaVasool - HackInOut 2019" | |||
| date = 2019-10-25T15:30:03+05:30 | |||
| draft = false | |||
| categories = ["projects"] | |||
| tags = ["fintech", "hackathon"] | |||
| type = "post" | |||
| url = "blog/2019/10/25/paisavasool-hackinout-2019" | |||
| author = "Rohan Verma" | |||
| @@ -2,7 +2,8 @@ | |||
| title = "Containerized development workflow using remote gopls server" | |||
| date = 2019-11-05T15:30:03+05:30 | |||
| draft = false | |||
| categories = ["golang"] | |||
| tags = ["golang", "docker"] | |||
| categories = ["golang", "notes"] | |||
| type = "post" | |||
| url = "blog/2019/11/05/containerized-dev-using-remote-gopls" | |||
| author = "Rohan Verma" | |||
| @@ -36,33 +37,37 @@ Let us look at the Dockerfile for this system. | |||
| ```Dockerfile | |||
| FROM ubuntu:xenial AS builder | |||
| RUN apt-get update | |||
| # Install system dependencies that we might need | |||
| RUN apt-get install -y gcc g++ | |||
| RUN apt-get update && \ | |||
| apt-get install -y gcc g++ libssl-dev cmake wget libpcre3 libpcre3-dev git | |||
| # Install Depencies like Go and Swig in our container. | |||
| WORKDIR /tmp | |||
| # Install Go | |||
| RUN wget https://dl.google.com/go/go1.12.9.linux-amd64.tar.gz | |||
| RUN tar -C /usr/local -xzf go1.12.9.linux-amd64.tar.gz | |||
| # Install Swig | |||
| RUN wget http://prdownloads.sourceforge.net/swig/swig-4.0.1.tar.gz | |||
| RUN tar -zxvf swig-4.0.1.tar.gz | |||
| RUN cd /tmp/swig-4.0.1 && ./configure && make && make install | |||
| # Create user | |||
| RUN useradd -m -r -u 1000 myuser | |||
| RUN groupmod -g 1000 myuser | |||
| # Replicate/fake the host system tree | |||
| RUN mkdir -p /home/myuser/code/go/myhostdir/myproject | |||
| RUN chown -R myuser:myuser /home/myuser/code/go/myhostdir/myproject | |||
| # Install Go. | |||
| RUN wget https://dl.google.com/go/go1.12.9.linux-amd64.tar.gz && \ | |||
| tar -C /usr/local -xzf go1.12.9.linux-amd64.tar.gz | |||
| # Install Swig. | |||
| RUN wget http://prdownloads.sourceforge.net/swig/swig-4.0.1.tar.gz && \ | |||
| tar -zxvf swig-4.0.1.tar.gz && \ | |||
| cd /tmp/swig-4.0.1 && ./configure && make && make install | |||
| ARG MY_USER_ID | |||
| ENV MY_USER_ID ${MY_USER_ID} | |||
| ARG MY_PWD | |||
| ENV MY_PWD ${MY_PWD} | |||
| RUN mkdir -p $MY_PWD | |||
| RUN useradd -r -m -u $MY_USER_ID myuser | |||
| RUN groupmod -g $MY_USER_ID myuser | |||
| USER myuser | |||
| WORKDIR /home/myuser/code/go/myhostdir/myproject | |||
| ENV PATH="/usr/local/go/bin:${MY_PWD}/go/bin:${PATH}" | |||
| RUN GOPROXY=https://proxy.golang.org GO111MODULE=on go get golang.org/x/tools/[email protected] | |||
| WORKDIR $MY_PWD | |||
| RUN GO111MODULE=on go get golang.org/x/tools/gopls@latest | |||
| CMD gopls -listen=":7050" | |||
| CMD /home/myuser/go/bin/gopls -listen=":7050" | |||
| ``` | |||
| Firstly, we install all the dependencies and then create | |||
| @@ -77,13 +82,28 @@ inside the container. | |||
| Finally, we install gopls in the container and then start it in the container | |||
| with the `-listen=":7050"` flag. | |||
| We will now build the image. | |||
| ```bash | |||
| mkdir -p go | |||
| docker build \ | |||
| --build-arg MY_PWD=${PWD} \ | |||
| --build-arg=MY_USER_ID=${MY_USER_ID} \ | |||
| -t myapp:latest . | |||
| ``` | |||
| Note, we also create a directory called `go` which will be the mock GOPATH | |||
| inside the container. | |||
| Now we can expose this port to our host machine. | |||
| ```bash | |||
| docker run -d --name "myproject" -u `id -u` -p 7050:7050 \ | |||
| -v /home/myuser/code/go/myhostdir/myproject:/home/myuser/code/go/myhostdir/ \ | |||
| myproject myproject:latest | |||
| docker run -d --name "myapp" \ | |||
| -u `id -u ${USER}` \ | |||
| -e "GOPATH=${PWD}/go" \ | |||
| -p 7050:7050 \ | |||
| -v ${PWD}:${PWD} myapp:latest | |||
| ``` | |||
| Notice, that we also mount the host source in the container with the same path, | |||
| @@ -96,8 +116,22 @@ flags we use for the language server to connect to the remote gopls server. | |||
| gopls -remote "localhost:7050" | |||
| ``` | |||
| For VSCode, you can add the following to your `settings.json` | |||
| ```json | |||
| { | |||
| "go.languageServerFlags": [ | |||
| "-remote=localhost:7050", | |||
| "-v" | |||
| ], | |||
| "go.useLanguageServer": true, | |||
| "go.gopath": "go" | |||
| } | |||
| ``` | |||
| After adding this flag, you will now be able to edit your source with all the | |||
| added benefits that come with a language server. | |||
| added benefits that come with a language server like autocompletion and | |||
| autoformatting. | |||
| Since this is an experimental feature, it might break (a lot). Do let me know | |||
| in the comments if this was helpful for you. | |||
| @@ -0,0 +1,70 @@ | |||
| +++ | |||
| title = "Creating archive pages grouped by year in Hugo" | |||
| date = 2019-11-15T15:30:03+05:30 | |||
| draft = false | |||
| tags = ["hugo", "blog", "golang"] | |||
| categories = ["tutorials"] | |||
| type = "post" | |||
| url = "blog/2019/11/15/archive-pages-group-by-year-hugo" | |||
| author = "Rohan Verma" | |||
| +++ | |||
| I was on the hunt to find out how to organize my [blog](/blog_list) and | |||
| [project](/project) archive pages by year in Hugo. After being unable to find | |||
| any easy solutions I decided I would sit down and write the go template to | |||
| render these pages myself. The idea was simple, iterate over the list divided | |||
| by year into sub lists and render tables, but it turned out to be a bit tricky. | |||
| Here is the template, hope it is useful for someone who wants to have a similar | |||
| page. | |||
| ```html | |||
| {{ define "title" -}} | |||
| Blog List | {{ .Site.Title }} | |||
| {{- end }} | |||
| {{ define "header" }} | |||
| {{ partial "masthead.html" . }} | |||
| {{ end }} | |||
| {{ define "main" }} | |||
| <header> | |||
| <h1>{{ .Title }}</h1> | |||
| </header> | |||
| <section> | |||
| {{ $prev := 3000}} | |||
| {{range .Site.RegularPages}} | |||
| {{if .Date}} | |||
| {{if gt $prev (.Date.Format "2006")}} | |||
| {{ if ne $prev 3000}} | |||
| </table> | |||
| {{ end }} | |||
| <h2>{{ .Date.Format "2006" }}</h2> | |||
| <table class="all-posts"> | |||
| {{end}} | |||
| <tr> | |||
| <td>{{.Date.Format "02 Jan"}}</td> | |||
| <td><a href="{{.Permalink}}">{{.Title}}</a></td> | |||
| </tr> | |||
| {{ $prev = .Date.Format "2006"}} | |||
| {{end}} | |||
| {{end}} | |||
| </table> | |||
| </section> | |||
| {{ end }} | |||
| {{ define "footer" }} | |||
| {{ partial "powered-by.html" . }} | |||
| {{ end }} | |||
| ``` | |||
| The above template loops through all the blogs (having a date) and renders | |||
| multiple tables | |||
| which are grouped by the year. We render `h2` tags with the year if the previous | |||
| year is greater than the current year. Followed | |||
| by a `<table>` tag having each next blog rendered as a row in the table. The | |||
| previous seen date is updated for the next iteration. In each iteration, before | |||
| rendering the table tag we check if the previous date was greater than the date | |||
| or`3000` (an arbitrarily high year) which we set as the previous seen year | |||
| before starting the loop, to decide if we want to close the table tag. In the | |||
| next iteration, the previous year will be the same as the current year, and so | |||
| we can continue to render rows. | |||
| @@ -0,0 +1,231 @@ | |||
| +++ | |||
| title = "Self hosted Netlify using docker-compose, gitea, and drone-ci" | |||
| date = 2019-11-15T15:30:03+05:30 | |||
| draft = true | |||
| tags = ["golang", "docker", "self hosted"] | |||
| categories = ["tutorials"] | |||
| type = "post" | |||
| url = "blog/2019/11/15/selfhosted-netlify" | |||
| author = "Rohan Verma" | |||
| +++ | |||
| I had been using netlify to deploy a few of my static sites. The process for | |||
| deployment is seamless and all you need to do is push to master. Pushing to | |||
| the develop branch or creating a pull request on github creates a mirror | |||
| with a unique URL which can be used to preview the site. | |||
| It worked well, but I often feel that I will eventually be tied down or stuck | |||
| to the service. One day the pricing will change or the service will | |||
| disappear. Also, for my small static sites, the features it offers are too much. | |||
| I also wanted to setup CI/CD for my other projects, and setting up my own CI/CD | |||
| pipeline and migrating static sites would be a good easy step to start. | |||
| This article is derived from [Self-hosting with Docker](https://blog.ssdnodes.com/blog/self-hosting-handbook/) by [Joel Hans](https://blog.ssdnodes.com/blog/author/joel/). I might skip a few details, which are covered there. | |||
| ```yaml | |||
| version: '2' | |||
| services: | |||
| proxy: | |||
| image: jwilder/nginx-proxy | |||
| container_name: proxy | |||
| restart: unless-stopped | |||
| labels: | |||
| com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true" | |||
| volumes: | |||
| - /var/run/docker.sock:/tmp/docker.sock:ro | |||
| - certs:/etc/nginx/certs:rw | |||
| - vhost.d:/etc/nginx/vhost.d | |||
| - html:/usr/share/nginx/html | |||
| - ./uploadsize.conf:/etc/nginx/conf.d/uploadsize.conf:ro | |||
| ports: | |||
| - "80:80" | |||
| - "443:443" | |||
| networks: | |||
| - "default" | |||
| - "proxy-tier" | |||
| proxy-letsencrypt: | |||
| image: jrcs/letsencrypt-nginx-proxy-companion | |||
| container_name: letsencrypt | |||
| restart: unless-stopped | |||
| environment: | |||
| - NGINX_PROXY_CONTAINER=proxy | |||
| volumes: | |||
| - /var/run/docker.sock:/var/run/docker.sock:ro | |||
| volumes_from: | |||
| - "proxy" | |||
| depends_on: | |||
| - "proxy" | |||
| networks: | |||
| - "default" | |||
| - "proxy-tier" | |||
| portainer: | |||
| image: portainer/portainer | |||
| container_name: portainer | |||
| restart: always | |||
| environment: | |||
| - VIRTUAL_HOST=docker.rohanverma.net | |||
| - LETSENCRYPT_HOST=docker.rohanverma.net | |||
| - [email protected] | |||
| volumes: | |||
| - ./portainer/:/data | |||
| - /var/run/docker.sock:/var/run/docker.sock | |||
| privileged: true | |||
| ports: | |||
| - "9000:9000" | |||
| gitea: | |||
| image: gitea/gitea:latest | |||
| container_name: gitea | |||
| restart: unless-stopped | |||
| environment: | |||
| - VIRTUAL_HOST=gitea.rohanverma.net | |||
| - LETSENCRYPT_HOST=gitea.rohanverma.net | |||
| - [email protected] | |||
| - VIRTUAL_PORT=3000 | |||
| - ROOT_URL=https://gitea.rohanverma.net | |||
| - DOMAIN=gitea.rohanverma.net | |||
| - PROTOCOL=http | |||
| - USER_UID=1000 | |||
| - USER_GID=1000 | |||
| volumes: | |||
| - ./gitea:/data | |||
| ports: | |||
| - "5000:3000" | |||
| - "222:22" | |||
| networks: | |||
| - proxy-tier | |||
| - default | |||
| drone: | |||
| container_name: drone | |||
| image: drone/drone:latest | |||
| restart: always | |||
| environment: | |||
| - DRONE_GITEA_SERVER=https://gitea.rohanverma.net | |||
| - DRONE_GIT_ALWAYS_AUTH=false | |||
| - DRONE_RUNNER_CAPACITY=3 | |||
| - DRONE_SERVER_HOST=drone.rohanverma.net | |||
| - DRONE_SERVER_PROTO=https | |||
| - DRONE_TLS_AUTOCERT=false | |||
| - DRONE_RPC_SECRET=xxxxxxxx | |||
| - DRONE_GITEA_CLIENT_ID=xxxxxxxxxxxxxxxxx | |||
| - DRONE_GITEA_CLIENT_SECRET=xxxxxxxxxxxxxxxxxx | |||
| - VIRTUAL_HOST=drone.rohanverma.net | |||
| - VIRTUAL_PORT=80 | |||
| - DRONE_USER_CREATE=username:rhnvrm,admin:true | |||
| - DRONE_DEBUG=true | |||
| volumes: | |||
| - /var/run/docker.sock:/var/run/docker.sock | |||
| - ./drone:/data | |||
| privileged: true | |||
| ports: | |||
| - "5151:80" | |||
| networks: | |||
| - default | |||
| drone-agent: | |||
| container_name: drone-agent | |||
| image: drone/agent:latest | |||
| command: agent | |||
| restart: always | |||
| depends_on: | |||
| - drone | |||
| privileged: true | |||
| volumes: | |||
| - /var/run/docker.sock:/var/run/docker.sock | |||
| environment: | |||
| - DRONE_RPC_SERVER=https://drone.rohanverma.net | |||
| - DRONE_RPC_SECRET=xxxxxxxx | |||
| - DRONE_RUNNER_CAPACITY=3 | |||
| - DRONE_RUNNER_NAME="local" | |||
| networks: | |||
| - default | |||
| rohanvermanet: | |||
| container_name: rohanvermanet | |||
| build: | |||
| dockerfile: Dockerfile | |||
| context: ../apps/rohanverma.net | |||
| ports: | |||
| - "8080:80" | |||
| environment: | |||
| - VIRTUAL_HOST=rohanverma.net | |||
| - LETSENCRYPT_HOST=rohanverma.net | |||
| - [email protected] | |||
| nextrohanvermanet: | |||
| container_name: nextrohanvermanet | |||
| build: | |||
| dockerfile: Dockerfile | |||
| context: ../apps/next.rohanverma.net | |||
| ports: | |||
| - "8079:80" | |||
| environment: | |||
| - VIRTUAL_HOST=next.rohanverma.net | |||
| - LETSENCRYPT_HOST=next.rohanverma.net | |||
| - [email protected] | |||
| volumes: | |||
| certs: | |||
| vhost.d: | |||
| html: | |||
| networks: | |||
| proxy-tier: | |||
| ``` | |||
| The drone.yml file | |||
| ```yml | |||
| --- | |||
| kind: pipeline | |||
| type: docker | |||
| name: default | |||
| steps: | |||
| - name: ssh commands for rohanverma.net | |||
| image: appleboy/drone-ssh | |||
| when: | |||
| branch: | |||
| - master | |||
| settings: | |||
| host: 159.89.175.2 | |||
| username: deploy | |||
| port: 22 | |||
| key: | |||
| from_secret: ssh_key | |||
| script_stop: true | |||
| script: | |||
| - cd /home/rhnvrm/apps/rohanverma.net | |||
| - git fetch origin | |||
| - git checkout origin/master | |||
| - cd /home/rhnvrm/proxy | |||
| - docker-compose build rohanvermanet | |||
| - docker-compose up -d rohanvermanet | |||
| - name: ssh commands for next.rohanverma.net | |||
| image: appleboy/drone-ssh | |||
| when: | |||
| branch: | |||
| - develop | |||
| settings: | |||
| host: 159.89.175.2 | |||
| username: deploy | |||
| port: 22 | |||
| key: | |||
| from_secret: ssh_key | |||
| script_stop: true | |||
| script: | |||
| - cd /home/rhnvrm/apps/next.rohanverma.net | |||
| - git fetch origin | |||
| - git checkout origin/develop | |||
| - cd /home/rhnvrm/proxy | |||
| - docker-compose build nextrohanvermanet | |||
| - docker-compose up -d nextrohanvermanet | |||
| ``` | |||
| @@ -57,7 +57,6 @@ | |||
| {{ $hackcss_mode := .Site.Params.hackcss.mode | default "hack" }} | |||
| {{ $hackcss_palette := .Site.Params.hackcss.palette | default "dark" }} | |||
| <body class="{{ if ne $hackcss_disabled true }}{{ $hackcss_mode }} {{ $hackcss_palette }} main container{{ end }}"> | |||
| {{ partial "body/darkmode.html" . }} | |||
| <header>{{ block "header" . }}{{ end }}</header> | |||
| <main>{{ block "main" . }}{{ end }}</main> | |||
| <footer> | |||
| @@ -17,49 +17,6 @@ | |||
| </div> | |||
| </div> | |||
| <br> | |||
| <h2>About</h2> | |||
| <h3>Work</h3> | |||
| I’m currently working as a Software Developer at | |||
| <a class="no-underline text-grey-dark" href="https://zerodha.com/products">Zerodha Tech</a> | |||
| where I am writing Golang, Python and a bit of Javascript to | |||
| build fintech products used at scale everyday. | |||
| <br><br> | |||
| Before Zerodha, I interned with Dell Technologies as a | |||
| Software Engineering Intern and graduated in the Summer of 2018 from | |||
| Shiv Nadar University, Dadri, India. | |||
| <br><br> | |||
| At Dell, I was part of a team that was building a | |||
| new end-to-end microservice based product using Golang (and Python) to solve an | |||
| invoice-to-order matching problem which had an effect of increasing | |||
| the cash flows for Dell and customer facing invoice accuracy | |||
| via last mile automation. | |||
| <br><br> | |||
| I have | |||
| also worked remotely during my participation in Google Summer | |||
| of Code in 2016 and contributed to the Open Source Apache | |||
| Allura Project that powers SourceForge.com. | |||
| <br><br> | |||
| Out of interest and curiosity, I have (little) experience with | |||
| Machine Learning and AI through my pursuit of a Machine Learning | |||
| Nanodegree which I earned through a MOOC curated by Udacity | |||
| which I undertook in the summer of 2017. | |||
| <br><br> | |||
| <h3>Personal</h3> | |||
| I am from New Delhi, India and am currently | |||
| based in Bengaluru, India. I write code for a living, | |||
| and often write code as a hobby, or to automate the | |||
| little things. You might find me lurking on online | |||
| message boards, online games and IRC as rhnvrm (an alias I took | |||
| long ago). | |||
| <br><br> | |||
| <h2>Social</h2> | |||
| @@ -106,6 +63,10 @@ | |||
| <h2>Blog</h2> | |||
| My blog is also available via <a href="/blog/index.xml">[RSS]</a> | |||
| <br><br> | |||
| You can read my <a class="no-underline text-grey-dark" href="/blog">blog</a> where | |||
| I try to write about what I am doing and things I find interesting. | |||
| I have organized my blog using categories | |||
| @@ -127,22 +88,18 @@ | |||
| <br><br> | |||
| <section> | |||
| <b>categories</b>: <br> | |||
| <b><a href="/categories">categories</a></b>: <br> | |||
| {{range ($.Site.GetPage "taxonomyTerm" "categories").Pages }} | |||
| <a href="{{.Permalink}}">{{lower .Title}}</a> | |||
| {{end}} | |||
| <br><br> | |||
| <b>tags</b>: <br> | |||
| <b><a href="/tags">tags</a></b>: <br> | |||
| {{range ($.Site.GetPage "taxonomyTerm" "tags").Pages }} | |||
| <a href="{{.Permalink}}">{{lower .Title}}</a> | |||
| {{end}} | |||
| </section> | |||
| <br> | |||
| My blog is also available via <a href="/blog/index.xml">[RSS]</a> | |||
| <br><br> | |||