.
HashiQube

The Ultimate Hands-on DevOps Lab in a Docker Container
🚀 About
HashiQube is your complete DevOps playground, designed to help engineers, developers, and anyone interested in learning or demonstrating HashiCorp products. It's a self-contained environment that runs all HashiCorp products and integrates with popular open-source DevOps/DevSecOps applications.
Key Features
Complete HashiCorp Stack: Run Vault, Terraform, Nomad, Consul, Waypoint, Boundary, Vagrant, Packer, and Sentinel in one place.
Additional DevOps Tools: Includes Minikube, Ansible AWX Tower, Traefik, and more to demonstrate integration with HashiCorp products.
Offline Capability: Once set up, an internet connection is no longer needed, making it perfect for demos, sales pitches, and learning environments.
Nested Containerization: HashiQube has a Docker daemon inside, allowing you to run containers using Kubernetes (Minikube), Nomad, or Docker run.
📋 Provision
bash docker/docker.sh
bash vault/vault.sh
bash consul/consul.sh
bash nomad/nomad.sh
bash boundary/boundary.sh
vagrant up --provision
docker compose exec hashiqube /bin/bash
bash hashiqube/basetools.sh
bash docker/docker.sh
bash docsify/docsify.sh
bash vault/vault.sh
bash consul/consul.sh
bash nomad/nomad.sh
bash boundary/boundary.sh
🎥 Introduction Video
Watch a short introduction to HashiQube. Make sure you have HashiQube running so you can follow along on your own machine!
🔗 Resources
Find more information about HashiQube on these channels:
- HashiCorp Blog Post
- HashiQube Website
- HashiQube GitHub
- HashiQube YouTube
- HashiQube Medium Articles
- HashiQube Terraform Registry Module
- Terraform Development Environment Article
🛠️ Basetools Provider
The Basetools provider installs essential tools that HashiQube provisioners need. This is one of the first provisioners that must be run. It installs:
swapspace rkhunter jq curl unzip software-properties-common bzip2 git make
python3.9 python3-pip python3-dev python3-venv python3-virtualenv golang-go
apt-utils ntp update-motd toilet figlet nano iputils-ping dnsutils iptables telnet
Basetools Provisioner Script
The script below automates the setup of basic tools in your HashiQube environment:
<!DOCTYPE html>
<html>
<head>
<title>HashiQube - A Hands on DevOps Development Lab Using All the HashiCorp Products and other Popular Applications such as Docker, Kubernetes, Traefik, Ansible, AWX Ansible Tower and loads more.</title>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-LWNG2RV7KC"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-LWNG2RV7KC');
</script>
<!-- script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5855657010614500" crossorigin="anonymous"></script -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta property="og:url" content="https://hashiqube.com/" />
<meta property="og:type" content="website" />
<meta property="og:title" content="HashiQube - The Ultimate Hands on DevOps Lab in a Docker Container" />
<meta property="og:description" content="HashiQube is a Hands on DevOps Development Lab Using All the HashiCorp Products and other Popular Applications such as Docker, Kubernetes, Traefik, Ansible, AWX Ansible Tower and loads more." />
<meta property="og:image" content="https://hashiqube.com/images/youtube-hashiqube-the-jedi-devops-lab.png" />
<meta charset="UTF-8">
<link rel="icon" type="image/png" href="/images/logo-bright.png">
<link rel="stylesheet" href="/docsify/lib/vue.css" disabled>
<link rel="stylesheet" href="/docsify/lib/buble.css" disabled>
<link rel="stylesheet" href="/docsify/lib/dark.css" disabled>
<link rel="stylesheet" href="/docsify/lib/pure.css" disabled>
<link rel="stylesheet" href="/docsify/lib/mermaid.min.css">
<link rel="stylesheet" href="/docsify/lib/docsify-accordion-style.css">
<!-- Theme: Simple (latest v0.x.x) -->
<link
rel="stylesheet"
href="/docsify/lib/docsify-darklight-theme-style.min.css"
title="docsify-darklight-theme"
type="text/css"
/>
<script src="/docsify/lib/mermaid.min.js"></script>
<style>
/*
Hashiqube Theme
Version 0.0.3
*/
:root {
--hashi-gradient: 90deg,
#370960 0%,
#ea216b 10%,
#ff5800 20%,
#fefb00 30%,
#61e190 40%,
#5cdeff 50%,
#61e190 60%,
#fefb00 70%,
#ff5800 80%,
#ea216b 90%,
#370960 100%;
--hashi-blue: #5cdeff;
--hashi-green: #61e190;
--hashi-yellow: #fefb00;
--hashi-orange: #ff5800;
--hashi-pink: #ea216b;
--hashi-purple: #370960;
--docsifytabs-border-color: #ededed;
--docsifytabs-tab-highlight-color: purple;
}
.yellow {
background: var(--hashi-yellow);
}
.orange {
background: var(--hashi-orange);
}
.blue {
background: var(--hashi-blue);
}
.green {
background: var(--hashi-green);
}
.purple {
background: var(--hashi-purple);
}
.pink {
background: var(--hashi-pink);
}
.header img {
width: 80%;
display: none;
top: 0px;
right: 0px;
}
.app-name-link img {
max-width: 160px;
-webkit-transition-property: all;
-webkit-transition-duration: 0.3s;
-webkit-transition-timing-function: ease;
}
.app-name-link img:hover {
transform: scale(1.3);
}
.sidebar-nav ul ul,
.sidebar nav ul ul {
margin-left: 0px;
}
.search .input-wrap {
margin-top: 10px !important;
}
aside.sidebar {
width: auto;
display: flex;
flex-direction: column;
padding-top: 110px;
}
aside.sidebar :nth-child(1) {
order: 2;
}
aside.sidebar :nth-child(2) {
order: 1;
}
aside.sidebar :nth-child(3) {
order: 3;
}
.sidebar-toggle {
position: fixed !important;
bottom: auto;
left: 0px;
right: 0px;
background: linear-gradient(var(--hashi-gradient));
display: block;
height: 70px;
padding: 0;
width: 100% !important;
}
.sidebar-toggle-button {
display: flex;
width: 70px;
height: 70px;
text-align: center;
flex-direction: column;
justify-content: center;
align-items: center;
background: var(--hashi-blue);
right: 0;
top: 0;
position: absolute;
}
.sidebar-toggle span {
background-color: #000000;
display: block;
margin-bottom: 4px;
width: 20px;
height: 2px;
}
.sidebar ul li a {
font-size: 18px;
}
#docsify-darklight-theme {
background-color: #000000;
background-repeat: no-repeat;
background-size: 30px;
background-position: center;
position: fixed;
right: 140px;
top: 0;
width: 70px;
left: auto;
height: 70px;
z-index: 1000;
}
.content {
padding-top: 10px;
left: 240px;
}
.markdown-section {
padding-top: 110px;
max-width: 1050px;
}
.markdown-section iframe {
border: 0px solid #eee;
}
.markdown-section pre>code,
.markdown-section code {
font-size: 1rem;
}
.footer {
position: relative;
/* display: none; */
text-align: center;
bottom: 10px;
}
.github-corner svg {
fill: transparent;
color: #ffffff;
padding: 0px;
margin: 0px;
margin-left: 0px;
position: relative;
right: 15px;
height: 70px;
width: 70px;
}
.github-corner {
border-bottom: 0;
position: fixed;
right: 70px;
text-decoration: none;
top: 0;
z-index: 1;
box-sizing: border-box;
width: 70px;
height: 70px;
margin-left: -12px;
overflow: hidden;
background: var(--hashi-purple);
z-index: 100;
box-sizing: border-box;
padding: 8px 0 0 5px;
}
.progress-bar {
background: linear-gradient(var(--hashi-gradient));
height: 7px;
position: fixed;
bottom: 0px;
left: 0px;
width: 100%;
padding-bottom: 10px;
}
.hasinav {
position: fixed;
left: auto;
right: 210px;
z-index: 100;
top: 0;
height: 70px;
display: flex;
}
.hasinav .qube {
width: 70px;
display: inline-flex;
box-sizing: border-box;
height: 70px;
align-items: center;
justify-content: center;
}
.hasinav .qube:hover {
opacity: 0.8;
}
.hasinav .qube img {
max-width: 30px;
max-height: 30px;
width: auto;
height: auto;
}
</style>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-MQ56PNF"
height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<!-- End Google Tag Manager (noscript) -->
<div class="header"><img title="HashiQube - DevOps Lab" alt="HashiQube - DevOps Lab" src="/images/hashiqube-banner.png"></div>
<div class="hasinav">
<a href="https://www.youtube.com/@hashiqube/featured" target="_blank" class="qube yellow"><img src="/images/youtube-logo.svg" border="0" alt="Youtube Channel" title="Youtube Channel"></a>
<a href="https://medium.com/search?q=hashiqube" target="_blank" class="qube green"><img src="/images/medium-logo.svg" border="0" alt="Medium Posts" title="Medium Posts"></a>
<a href="https://www.linkedin.com/in/riaannolan/" target="_blank" class="qube blue"><img src="/images/linkedin-logo.png" border="0" alt="Riaan Nolan Linkedin" title="Riaan Nolan Linkedin"></a>
<a href="https://www.hashicorp.com/ambassadors/directory?q=riaan" target="_blank" class="qube pink"><img src="/images/hashicorp-logo.svg" border="0" alt="Riaan Nolan Hashicorp Ambassador" title="Riaan Nolan Hashicorp Ambassador"></a>
</div>
<div id="app"></div>
<article class="markdown-section" id="main"></article>
<script>
window.$docsify = {
routerMode: 'history', //hash (default) or history, history mode (SEO friendly) is possible if you host on https://www.netlify.com/ see rewrite rules in _redirects file
notFoundPage: '/',
nameLink: '/',
basePath: '/',
alias: {
'/.*/SUMMARY.md': '/SUMMARY.md'
},
topMargin: 80,
logo: '/images/logo-bright.png',
name: 'HashiQube',
repo: 'https://github.com/star3am/hashiqube',
search: 'auto',
auto2top: true,
relativePath: false,
homepage: 'README.md',
loadSidebar: 'SUMMARY.md',
subMaxLevel: 3,
formatUpdated: '{MM}/{DD} {HH}:{mm}',
plugins: [
function (hook, vm) {
hook.beforeEach(function (html) {
return html.replace(/{% *.* %}/mg, '')
})
}
],
markdown: {
renderer: {
code: function(code, lang) {
if (lang === "mermaid") {
return (
'<div class="mermaid">' + mermaid.render('mermaid-svg-' + num++, code) + "</div>"
);
}
if (lang === 'drawio') {
if (window.drawioConverter) {
console.log('drawio')
return window.drawioConverter(code)
} else {
return `<div class='drawio-code'>${code}</div>`
}
}
return this.origin.code.apply(this, arguments);
}
}
},
themeable: {
readyTransition : true,
responsiveTables: true
},
// Style Guide: https://github.com/dracula/dracula-theme
darklightTheme: {
siteFont: "PT Sans",
defaultTheme: 'light',
codeFontFamily: 'Roboto Mono, Monaco, courier, monospace',
bodyFontSize: '18px',
dark: {
accent: '#8be9fd',
toggleBackground: '#f8f8f2',
background: '#240129',
textColor: '#f8f8f2',
codeTextColor: '#5cdeff',
codeBackgroundColor: '#000524',
borderColor: '#0d2538',
blockQuoteColor: '#5cdeff',
highlightColor: '#fefb00',
sidebarSublink: '#61e190',
codeTypeColor: '#5cdeff',
coverBackground: 'linear-gradient(to left bottom, hsl(118, 100%, 85%) 0%,hsl(181, 100%, 85%) 100%)',
toggleImage: 'url(/docsify/lib/docsify-darklight-theme-sun.svg)'
},
light: {
accent: '#ed2f74',
toggleBackground : '#091a28',
background: '#ffffff',
textColor: '#444444',
codeTextColor : '#370960',
codeBackgroundColor : '#f8f8f8',
borderColor : 'rgba(0, 0, 0, 0.07)',
blockQuoteColor : '#858585',
highlightColor : '#d22778',
sidebarSublink : '#34495e',
codeTypeColor : '#370960',
coverBackground: 'linear-gradient(to left bottom, hsl(118, 100%, 85%) 0%,hsl(181, 100%, 85%) 100%)',
toggleImage: 'url(/docsify/lib/docsify-darklight-theme-moon.svg)'
}
},
tabs: {
persist: true, // default
sync: true, // default
tabComments: true, // default
tabHeadings: true // default
},
// pagination: {
// crossChapter: true
// },
}
var num = 0;
mermaid.initialize({ logLevel:0, startOnLoad: false, themeCSS:'.label { font-family: Source Sans Pro,Helvetica Neue,Arial,sans-serif; }' });
</script>
<script src="/docsify/lib/docsify.min.js"></script>
<script src="/docsify/lib/plugins-emoji.min.js"></script>
<script src="/docsify/lib/docsify-copy-code.js"></script>
<script src="/docsify/lib/plugins-search.min.js"></script>
<script src="/docsify/lib/prism-bash.js"></script>
<script src="/docsify/lib/prism-yaml.js"></script>
<script src="/docsify/lib/prism-log.js"></script>
<script src="/docsify/lib/prism-hcl.js"></script>
<script src="/docsify/lib/prism-docker.js"></script>
<script src="/docsify/lib/prism-python.js"></script>
<script src="/docsify/lib/prism-ruby.js"></script>
<script src="/docsify/libprism-groovy.min.js"></script>
<script src="/docsify/libprism-typescript.min.js"></script>
<script src="/docsify/lib/docsify-darklight-theme-index.min.js"></script>
<!-- script src="/docsify/lib/docsify-pagination.min.js"></script -->
<script src="/docsify/lib/docsify-slides.min.js"></script>
<script src="/docsify/lib/docsify-accordion.js"></script>
<script src="/docsify/lib/docsify-drawio-viewer.min.js"></script>
<script src='/docsify/lib/docsify-drawio-drawio.js'></script>
<script src="/docsify/lib/docsify-tabs.js"></script>
<div class="footer"></div>
<div class="progress-bar"></div>
</body>
</html>
🌐 HashiQube.com Deployment
WORK IN PROGRESS
As you might expect, HashiQube.com is deployed using HashiCorp tools - specifically, Waypoint. Here's how it works:
1. Set Up Local Environment
# Bring up HashiQube locally with the necessary components
vagrant up --provision-with basetools,docker,terraform,nomad,waypoint
# SSH into HashiQube
vagrant ssh
2. Configure AWS Credentials
Create or edit ~/.aws/config
:
[default]
region =
aws_access_key_id =
aws_secret_access_key =
output = json
3. Navigate to Project Directory
cd /vagrant
4. Initialize Waypoint
waypoint init
Output:
✓ Configuration file appears valid
✓ Connection to Waypoint server was successful
✓ Project "hashiqube" and all apps are registered with the server.
✓ Project "hashiqube" pipelines are registered with the server.
Project initialized!
You may now call 'waypoint up' to deploy your project or
commands such as 'waypoint build' to perform steps individually.
5. Deploy with Waypoint
waypoint up
This command builds and deploys the HashiQube website. The process includes:
- Building a Docker image
- Pushing to ECR
- Deploying to ECS
- Setting up load balancers and target groups
6. Cleanup Resources (When Needed)
waypoint destroy
👤 Connect
Please connect with the creator: