WordPress to hugo

It has been some time since I last wrote a blog post and a large portion of that is because for the longest time I’ve been wanting to move it off of wordpress and onto something else that is a little more lightweight and easier to work with.

I finally decided to bite the bullet and move it to hugo hosted out of an S3 bucket, so here’s a guide on how to do that.

  1. Use the wordpress to hugo exporter
  2. Install hugo and a theme.
  3. The exporter is designed for an older version of hugo so it doesn’t do a perfect job of translating things to hugo… you can fix it up easily enough though.

    hugo new site <my-website-name>
    cp -r my-export/post/* my-website-name/content/post/
    cp -r my-export/wp-page(s) my-website-name/content/wp-page(s)
    
  4. If you need to customize the layout for your pages then create a relevant HTML template under my-website-name/layouts/indexes/my-page.html

  5. Compile and test your hugo site.

    hugo server --theme=my-hugo-theme --buildDrafts
    
  6. Now it’s time to create an SSL certificate for your website using AWS certificate manager.

    {
      "AWSTemplateFormatVersion" : "2010-09-09",
      "Description" : "My blog certs",
    
      "Resources": {
        "RoshambootRootCert": {
          "Type" : "AWS::CertificateManager::Certificate",
          "Properties" : {
            "DomainName" : "<my-domain-name>"
          }
        }
      }
    }  
    
  7. In the AWS console navigate to Certificate Manager and select your newly created certificate. Make a note of the ARN, you will need it for the next part.

  8. Now to create the s3 bucket and cloudfront CDN.

    {
      "AWSTemplateFormatVersion" : "2010-09-09",
      "Description" : "My blog",
    
      "Resources": {
        "MyBlogCloudFront": {
          "Type" : "AWS::CloudFront::Distribution",
          "Properties" : {
            "DistributionConfig" : {
              "DefaultRootObject": "index.html",
              "PriceClass": "PriceClass_All",
              "Enabled": true,
              "Aliases": ["<my-domain-name>.com", "www.<my-domain-name>.com"],
              "CustomErrorResponses" : [
                {
                  "ErrorCode": 403,
                  "ResponsePagePath": "/404.html",
                  "ResponseCode": "404",
                  "ErrorCachingMinTTL": 300
                },
                {
                  "ErrorCode": 404,
                  "ResponsePagePath": "/404.html",
                  "ResponseCode": "404",
                  "ErrorCachingMinTTL": 300
                }
              ],
              "ViewerCertificate": {
                "SslSupportMethod": "sni-only",
                "AcmCertificateArn": "<certificate-ARN>",
                "MinimumProtocolVersion": "TLSv1"
              },
              "DefaultCacheBehavior": {
                "TargetOriginId": "<my-blog-bucket>-origin",
                "ViewerProtocolPolicy": "redirect-to-https",
                "DefaultTTL": 1800,
                "MinTTL": 0,
                "Compress": true,
                "ForwardedValues": {
                  "QueryString": false,
                  "Cookies": {
                    "Forward": "none"
                  }
                }
              },
              "Origins": [{
                "Id": "<my-blog-bucket>-origin",
                "DomainName": "<my-blog-bucket>.s3-website-<bucket-region>.amazonaws.com",
                "OriginPath": "",
                "CustomOriginConfig": {
                  "OriginProtocolPolicy": "http-only",
                  "HTTPPort": 80,
                  "HTTPSPort": 443,
                  "OriginSSLProtocols": [
                    "TLSv1",
                    "TLSv1.1",
                    "TLSv1.2"
                  ]
                }
              }]
            }
          }
        },
    
        "MyBlogBucket": {
          "Type" : "AWS::S3::Bucket",
          "Properties" : {
            "BucketName" : "<my-blog-bucket>",
            "AccessControl" : "PublicRead",
            "WebsiteConfiguration" : {
              "IndexDocument": "index.html",
              "ErrorDocument": "404.html",
              "RoutingRules": [{
                "RedirectRule": {
                  "ReplaceKeyWith": "index.html"
                },
                "RoutingRuleCondition": {
                  "KeyPrefixEquals": "/"
                }
              }]
            }
          }
        },
    
        "MyBlogBucketPolicy": {
          "Type" : "AWS::S3::BucketPolicy",
          "Properties" : {
            "Bucket" : { "Ref" : "MyBlogBucket" },
            "PolicyDocument": {
              "Version": "2012-10-17",
                "Statement": [{
                    "Sid": "PublicReadGetObject",
                    "Effect": "Allow",
                    "Principal": "*",
                    "Action": [ "s3:GetObject" ],
                    "Resource": [ "arn:aws:s3:::<my-blog-bucket>/*" ]
                }]
            }
          }
        }
      }
    }
    
  9. Generate the content for your website.

    hugo -b "https://my-blog.com" --theme my-theme
    
  10. Publish the content to your website.

    aws s3 sync my-website-name/public/ s3://my-blog-bucket --delete
    

And as a bonus here is a circle CI config and Makefile for some CD goodness

dependencies:
  override:
    - go get github.com/spf13/hugo:
        timeout: 240
test:
  override:
    - echo "nop!"
deployment:
  prod:
    branch: master
    commands:
      - make build
      - make deploy
.PHONY: build deploy-infra deploy

build:
	hugo -b "https://my-blog.com" --theme my-theme

deploy-infra:
	docker run --rm -v $(shell pwd):/cwd -e AWS_ACCESS_KEY -e AWS_SECRET_KEY -e AWS_SESSION_TOKEN -e AWS_DEFAULT_REGION realestate/stackup:latest my-blog up -t cloud-formation-template.json

deploy:
	aws s3 sync app/public/ s3://my-blog-bucket --delete
comments powered by Disqus