Pre-Requisites
There are a few tools that you should have on your computer before beginning this project. Specific setup instructions for these pre-requisites are out of scope of this project.
Windows 10
- Visual Studio Code - Best Open Source IDE. Just get it.
- Azure CLI 2.0
- Git Bash for Windows
MacOS
- Visual Studio Code
- Azure CLI 2.0
- Homebrew
- Git [
brew install git
] on the bash shell
Create Hugo Website Locally
Follow the instructions in the Hugo Quick Start guide to build your website. I’ve outlined a couple of changes to the instructions below. MacOS users can follow the Quick Start instructions exactly.
Download and install Hugo with the below steps:
PS C:\> mkdir Hugo
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/15/2018 1:11 PM Hugo
PS C:\> cd Hugo
PS C:\Hugo> wget https://github.com/gohugoio/hugo/releases/download/v0.37.1/hugo_0.37.1_Windows-64bit.zip -outfile hugo_install.zip
PS C:\Hugo> Expand-Archive hugo_install.zip"
PS C:\Hugo> set PATH=%PATH%;C:\Hugo\hugo_install
Close and open your PowerShell window to have the newly added path to Hugo active.
Create a parent directory and navigate to it before creating the site.
PS C:\> mkdir website
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/15/2018 12:40 PM website
PS C:\> cd website
PS C:\website> hugo new site quickstart
Then ensure you are in the parent directory and initialize the local Git repository.
PS C:\website> ls
Directory: C:\website
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 3/15/2018 12:45 PM quickstart
PS C:\website> git init
Initialized empty Git repository in C:/website/.git/
The instructions show commands that are Linux/Mac OS. These mostly work in Windows Powershell leave off any ;\
as they aren’t necessary.
The instructions also contain the following line:
echo 'theme = "ananke"' >> config.toml
This inserts the text into the config.toml but the text in incorrectly encoded and instead looks like this:
t h e m e = " a n a n k e "
Instead run that line as follows:
bash
echo 'theme = "ananke"' >> config.toml
exit
This assumes that you’ve got Git bash for Windows installed.
Alternatively you can just edit the config.toml in your favorite text editor and add that line.
Create Private GitHub Repository
This step requires a GitHub developer account if you want to have your site source code private. If you don’t care then go ahead and create a public repository.
We already initialized a local Git repository so now we will link it to our GitHub Repository.
PS C:\website> git remote add origin git@github.com:user/testweb.git
PS C:\website> git add .
PS C:\website> git commit -m "First Commit"
PS C:\website> git push -u origin master
We have now successfully initialized and pushed our website source to GitHub
One item to add is a .gitignore file to ensure the public directory is not pushed to GitHub this directory contains the compiled website files from Hugo.
PS C:\website> echo "quickstart/public/" >> .gitignore
Create Azure Storage Account v2
We are going to be using Azure CLI 2.0 for this work. You should have already set this up from the pre-requisites section. I’m going to assume that you only have one subscription attached to your Microsoft account here.
az login
az group create --name "Website" --location "North Central US"
az storage account create --name "websitestor45" --resource-group "Website" --location "North Central US" --sku Standard_RAGRS --kind StorageV2 --https-only true --access-tier Hot
az storage container create --account-name "websitestor45" --name "website" --public-access container
Our redundant storage account has been created with a publicly available container for our website content.
Create Azure CDN Profile and Namespace
Now on to creating the CDN profile and a namespace linked to our storage account container.
az cdn profile create --resource-group "Website" --name website --sku Premium_Verizon
az cdn endpoint create --resource-group "Website" --name website454 --profile-name "website" --origin websitestor45.blob.core.windows.net --no-http --origin-path "/website" --query-string-caching NotSet --enable
-compression false
az cdn custom-domain create -resource-group "Website" --endpoint-name website --profile-name website -name website --hostname www.example.com
This gets the CDN setup with your custom domain. Next is to enable SSL.
NOTE: You must have your WHOIS contact info up to date. A Domain Verification e-mail will come from from Digicert on behalf of Verizon which you must be able to respond to in order for the certificate request to be completed.
az cdn custom-domain enable-https --endpoint-name website --name website --profile-name website --resource-group "Website"
The requests are only processed within typical North American business hours. So if you run this outside of those hours it won’t be processed until the next business day. Even within business hours it can be a few hours before you receive the domain validation e-mail.
After you have verified that you own the domain. It will take an additional 90 minutes to 6 hours to have the certificate propagate through the global CDN network.
Configure Azure Premium CDN Rules
Unfortunately at this time you will need to use a web based GUI to configure these.
Login to the Azure Portal with your credentials. Then select Resource Groups from the left bar, click on your Website resource group you created in earlier steps and then click on your CDN Profile that you also created earlier.
Click on the Manage button to have the CDN management portal open in a new tab.
Once the management portal opens go to the HTTP Large menu and select Rules Engine
Click the Add New button and configure the below rules.
For ease of setup please copy the RegEx below:
Rule 1 : ((?:[^\?]*\/)?)($|\?.*) $1index.html$2
Rule 2: ((?:[^\?]*\/)?[^\?\/.]+)($|\?.*) $1/index.html$2
Save the rule and add another as below for caching rules.
Then another rule to bypass caching of the CMS configuration file.
Now to wait 90 minutes to 4 hours for rule propagation. The Pending XML will change to Active XML when the propagation of the rule is complete.
While we wait let’s move on to creating the VSTS CI/CD Pipeline
Create Visual Studio Online CI/CD Pipeline
Go to Visual Studio Online and activate your free Visual Studio Online tenant.
Once you are signed in, create a new Project. Go into the new Project.
Select Build and Release and then select Builds. From there click new to start a new CI/CD pipeline.
Select Process at the top. Set your build agent queue type. It should be set to Hosted.
Add your GitHub repository.
Click the + on Phase 1 and add/install the Hugo build extension.
Configure the Hugo build task with the illustrated settings. Your source should be the folder in the GitHub repository that contains the website source files. The destination should be source_folder/public.
Next add/install the AzureBlob File Copy build task. Select the correct subscription, the public folder from the earlier step as the source. Then enter the storage account name, the container that you setup in the previous steps. Also add the
/SetContentType
in Additional Arguments as by default all MIME content types get set to application/octet-stream which will not work. Now unfortunately not all file types are correctly set by the /SetContentType
so we have to run a custom PowerShell script to catch those other file types.
Open PowerShell ISE on your computer and paste this code:
Make the appropriate changes to the code for your storage account. As the code above suggests DO NOT paste your storage account key in your script. I added a parameter in which I could pass the key through an additional argument. This is somewhat better though using Azure Key Vault is a much better idea. Here’s the additional code to add for the parameter. Another addition is for the CMS config.yml and Markdown files to have it’s content type set correctly.
Param(
[string]$StorageAccountKey
)
#Add these two items to the SWITCH statement
".yml" { $ContentType = "text/yaml" }
".md" { $ContentType = "text/markdown" }
Delete the existing $StorageAccountKey
variable declaration and save.
Save the file in the root of your local git repository as fixContentType.ps1 and push the changes to your GitHub repository.
Add and configure the Azure PowerShell script:FilePath build task as shown. Ensure you specify your storage account key in the script arguments area.
Save and Queue your new CI/CD pipeline.
Go into your build and monitor the build process. You can view the logs to see if there are any errors in the build process.
Ensure that the CDN rules are now active and you should be able to visit your custom domain at https://www.example.com and see your website.
Now let’s get CMS functionality activated.
Add Netlify CMS and Authentication Micro-service
GitHub Authentication Micro Service
First let’s create a GitHub OAuth application. Pick a unique Web App name. The callback URL will be https://webappname.azurewebsite.net/callback
Follow these Instructions to create the OAuth Application
You should have a Client ID and Client Secret. Save those for the next step.
Next let’s create a free Azure Web App.
NOTE: Replace gh-auth-service with the unique name you picked earlier. This forms the Web App URL as discussed earlier. Replace the OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET values with the values you obtained from creating the OAuth Application in GitHub.
az login
az appservice plan create --resource-group "Website" --name "FreePlan" --sku FREE
az webapp create --resource-group "Website" --plan "FreePlan" --name "gh-auth-service" --deployment-source-branch master --deployment-source-url https://github.com/vencax/netlify-cms-github-oauth-provider.git
az webapp config appsettings set --name "gh-auth-service" --resource-group "Website" --settings NODE_ENV=production OAUTH_CLIENT_ID=f432a9casdff1e4b79c57 OAUTH_CLIENT_SECRET=pampadympapampadympapampadympa
az webapp restart --name "gh-auth-service" --resource-group "Website"
Netlify CMS Installation and Configuration
In your local git repo add a folder called admin under the static folder. Your tree should be: root/website/static/admin
Create a new filed called index.html
in this folder and paste the following code in it:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Content Manager</title>
<!-- Include the styles for the Netlify CMS UI, after your own styles -->
<link rel="stylesheet" href="https://unpkg.com/netlify-cms@^1.0.0/dist/cms.css" />
</head>
<body>
<!-- Include the script that builds the page and powers Netlify CMS -->
<script src="https://unpkg.com/netlify-cms@^1.0.0/dist/cms.js"></script>
</body>
</html>
Save this file. Next create another new file called config.yml
. Paste the following into it:
backend:
name: github
repo: dude/website
branch: master
base_url: https://gh-auth-service.azurewebsites.net
publish_mode: editorial_workflow
media_folder: "quickstart/static/images/uploads"
public_folder: "/images/uploads"
collections:
- name: "posts" # Used in routes, e.g., /admin/collections/blog
label: "Posts" # Used in the UI
folder: "quickstart/content/blog" # The path to the folder where the documents are stored
create: true # Allow users to create new documents in this collection
slug: "{{year}}-{{month}}-{{day}}-{{slug}}" # Filename template, e.g., YYYY-MM-DD-title.md
fields: # The fields for each document, usually in front matter
- {label: "Layout", name: "layout", widget: "hidden", default: "post"}
- {label: "Title", name: "title", widget: "string"}
- {label: "Publish Date", name: "date", widget: "datetime"}
- {label: "Description", name: "description", widget: "text"}
- {label: "Rating (scale of 1-5)", name: "rating", widget: "number"}
- {label: "Body", name: "body", widget: "markdown"}
Ensure that you are customizing it with your repository information. Change the base_url
setting to your authentication micro service URL.
Push the changes to the GitHub repository and wait 15 minutes for build pipeline to complete and the CDN cache to expire.
git add .
git commit -m "Netlify Deployment"
git push
Final Testing
Navigate to your custom domain CMS route https://www.example.com/admin/. A page with a “Login to GitHub” button should appear. Click it and your custom GitHub authentication micro service should launch a window that will prompt you to authorize it to use your GitHub credentials to login to the CMS. After that you should be taken into the CMS portal.
From there you can test the editorial workflow, creating new Posts etc. After Publishing a new post you should see the new content appear within 5-15 minutes on the main site.
Now there can be two simultaneous development streams. One for content creators, and one for developers extending the sites functionality and facilitating any UI enhancements. Content creators would use the CMS, and developers would be making use of local development and pushing those changes to the repository.