Set up a simple homepage with an auto-deploy tekton pipeline.
All checks were successful
semver Build semver has succeeded
build-homepage Build build-homepage has succeeded

This commit is contained in:
Tom Alexander 2023-07-08 23:01:12 -04:00
commit 85f3b31480
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
10 changed files with 307 additions and 0 deletions

63
.lighthouse/triggers.yaml Normal file
View File

@ -0,0 +1,63 @@
apiVersion: config.lighthouse.jenkins-x.io/v1alpha1
kind: TriggerConfig
spec:
postsubmits:
- name: semver
agent: tekton-pipeline
branches:
- ^main$
- ^master$
context: homepage
max_concurrency: 1
# Override https-based url from lighthouse events.
clone_uri: "git@code.fizz.buzz:talexander/homepage.git"
pipeline_run_spec:
serviceAccountName: build-bot
pipelineRef:
name: semver
namespace: lighthouse
workspaces:
- name: git-source
volumeClaimTemplate:
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
subPath: homepage-source
params: []
- name: build-homepage
agent: tekton-pipeline
branches:
- "^v[0-9]+\\.[0-9]+\\.[0-9]+$"
context: build-docker
max_concurrency: 1
# Override https-based url from lighthouse events.
clone_uri: "git@code.fizz.buzz:talexander/homepage.git"
pipeline_run_spec:
serviceAccountName: build-bot
pipelineRef:
name: build-docker-pipeline
workspaces:
- name: git-source
volumeClaimTemplate:
spec:
storageClassName: "nfs-client"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
subPath: git-source
- name: docker-credentials
secret:
secretName: harbor-plain
params:
- name: image-name
value: "harbor.fizz.buzz/private/homepage"
- name: path-to-image-context
value: .
- name: path-to-dockerfile
value: docker/server/Dockerfile

0
README.md Normal file
View File

11
docker/server/Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM alpine:3.18
RUN apk add --no-cache bash nginx
RUN addgroup web && adduser -D -G web web && install -d -D -o web -g web -m 700 /srv/http/public
RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
COPY --chown=web:web docker/server/nginx.conf /srv/http
COPY --chown=web:web docker/server/headers.include /srv/http
COPY --chown=web:web static/ /srv/http/public/
ENTRYPOINT ["/usr/sbin/nginx", "-c", "/srv/http/nginx.conf", "-e", "stderr", "-g", "daemon off;"]

35
docker/server/Makefile Normal file
View File

@ -0,0 +1,35 @@
IMAGE_NAME:=homepage
# REMOTE_REPO:=harbor.fizz.buzz/private
.PHONY: all
all: build push
.PHONY: build
build:
docker build -t $(IMAGE_NAME) -f Dockerfile ../
.PHONY: push
push:
ifdef REMOTE_REPO
docker tag $(IMAGE_NAME) $(REMOTE_REPO)/$(IMAGE_NAME)
docker push $(REMOTE_REPO)/$(IMAGE_NAME)
else
@echo "REMOTE_REPO not defined, not pushing to a remote repo."
endif
.PHONY: clean
clean:
docker rmi $(IMAGE_NAME)
ifdef REMOTE_REPO
docker rmi $(REMOTE_REPO)/$(IMAGE_NAME)
else
@echo "REMOTE_REPO not defined, not removing from remote repo."
endif
.PHONY: run
run:
docker run --rm -i -t -p "8080:8080" $(IMAGE_NAME)
.PHONY: shell
shell:
docker run --rm -i -t -p "8080:8080" --entrypoint /bin/bash $(IMAGE_NAME)

View File

@ -0,0 +1,16 @@
# Enable HTTP Strict Transport Security (HSTS) to force clients to
# always connect via HTTPS (do not use if only testing)
add_header Strict-Transport-Security "max-age=31536000;" always;
# Enable cross-site filter (XSS) and tell browser to block detected
# attacks
add_header X-XSS-Protection "1; mode=block" always;
# Prevent some browsers from MIME-sniffing a response away from the
# declared Content-Type
add_header X-Content-Type-Options "nosniff" always;
# Disallow the site to be rendered within a frame (clickjacking
# protection)
add_header X-Frame-Options "DENY" always;
# Surrogate Control sets CDN caching behavior.
add_header Surrogate-Control "public, max-age=86400";
add_header Cache-Control "public, max-age=120";

42
docker/server/nginx.conf Normal file
View File

@ -0,0 +1,42 @@
user web;
worker_processes 4;
# Speed up regular expressions.
pcre_jit on;
error_log stderr debug;
events {
# Connections per worker process.
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_tokens off;
client_max_body_size 1m;
sendfile on;
tcp_nopush on;
include headers.include;
server {
listen 8080;
root /srv/http/public;
location / {
index index.html index.htm;
if (-d $request_filename) {
rewrite [^/]$ $http_x_forwarded_proto://$http_host$uri/ redirect;
}
}
location /healthz {
access_log off;
add_header 'Content-Type' 'application/json';
return 200 '{"status":"OK"}';
}
}
}

View File

@ -0,0 +1,73 @@
==================================================================
https://keybase.io/tomalexander
--------------------------------------------------------------------
I hereby claim:
* I am an admin of https://fizz.buzz
* I am tomalexander (https://keybase.io/tomalexander) on keybase.
* I have a public key with fingerprint 20BA 994C 3993 5467 A337 BCFF 7E36 5E73 37BD 466E
To do so, I am signing this object:
{
"body": {
"key": {
"eldest_kid": "0101b8ea765573023535452721958f4dbf5acdf01b75f6f11048c344ea77f14ab4b50a",
"fingerprint": "20ba994c39935467a337bcff7e365e7337bd466e",
"host": "keybase.io",
"key_id": "7e365e7337bd466e",
"kid": "010145c375961ef994499dae6f6096cf9294ec5e56ed5c2a29c146076dd78bd041930a",
"uid": "649686c722ecf6d6beb66a67cdcfa300",
"username": "tomalexander"
},
"service": {
"hostname": "fizz.buzz",
"protocol": "https:"
},
"type": "web_service_binding",
"version": 1
},
"ctime": 1558368226,
"expire_in": 157680000,
"prev": "98cd64964fddf3863b5985ad3c15ca086a94d1ceb7a84ebfa83cfb3db5b26f22",
"seqno": 10,
"tag": "signature"
}
which yields the signature:
-----BEGIN PGP MESSAGE-----
owFtkntQVHUUx3nGIxwhilcQcG0IlPA+f/deQmZkyFHMBxNuZsB6H78Ll8fusrss
sLxyQkBkHOiBBMa4NcZjCgxyIEubIUhWGUTDSVImJZ4VjmSChGX3Mjr90++f35zz
+34/55zfnLp1zg7ujhaX3PaXI1yWHS/N8w6pk5fnihFeLxYhscVINly7YI4ITWZt
tiwisQiKoRjPQI4GFEUTKE5QBEVSOI1jLMVIpMhLFCeIkiKiKQlIGIaSjECQpOKg
JYzkeJKnUA6JRiRZlwGNBqOsMytYHOU5liUFgmUVHqA5gqB5QZJoSAAK0mokkgBA
xZipN6kOpTmeM8EYWa/klEC71t7/6P/rm6QEgqZYgEFJqUWyrMhBIAGUBYLE4iwJ
BQpSAIqUgHM4K2AkQGkgijTDiyiJscRa3/lrOECygAECjeNQkIAIeMgDwAFaEAWJ
I1BUFZqgUcflQkVt1udyObCQ04nQiJRGI8qLRRag+rnqNI9Vkmy1xvD5VqtiNhj1
Zr2gz1HSmWazwRSr2sxFBlVXAHntY4KWl3Wi8pGKwwKNJlmvQ2IxRSmYZRWJURRD
AAbHQTQCCw2yEWplVUHRgEGVo9aBFgXJMoIIyAMsICVRlAgGEDzFMhQnEgJGCRzK
AI4lRUyAPM0xJOQljiEEiSdEnuJxIOE4og6Vp9MrcIVq5jIUqEnO0HHmfCNESj2P
OBEuDo7uDiF+4S7+e5v7lneF2b57vjrhyfa5Oqmr5+Dp4f0k89WG9f/EPSNFJwX1
XWrdjqYnJ61G2s6cCs0ejwv5+cxw74TwVkVkjbWlO/5cVv/p57ZmG0Jn/I8t4b8F
f3u65sLNv1tG9trf9Nt/rtPSFF85rn12o19H6uiLlSex4cDZD+/XhOY0bjpbpEtO
dWrdPXE+Zqzk7Zuzj6Le+bL49tYdUdTKSHXbtGYl6IfWY6vWAS84uH1zxpXEpg+u
/HLPZ6dHe9lTJQvTU1teP+BGhjdoKiuc/Pe9MetvDjvYmOH6p1OtH894LGOBeRsW
tzzd2fPeDe3XDYNVN+xfEKMNHg+8uzpXCydmHvqGdGs+2mjbf9Dz1fq2Te9evBWw
c9/3+vLYI2B2wjrVPr5nyDXFpa+sNT23/q+MjqIe+wthMzHbZpoD0hzv1nX7fhwX
dKIx0bEcTxj/ZOBQgmYu2fNkUttwdsvdkgiNWy1qRwYG9T7eXd0jYz8dr8qpsx3u
vSOXpo35pXstBY6+ZnjQtbCobb7wfvX4fNq6moXLZXlVvWfr0XuTh6NszcXo+Tup
KwXOXvWbp8Mrl1ofug0vNu0I+fTX/q5tu/tPZZK3HAoq7fjxH4dHj9o6Kioirn2O
pMuTwehQeVJQVuKItbsBzF/LCtdct43PRxx1T/ksxcu3P2b9Lmdq8VBEguVimEvW
iQDvnj1/xHs/usrelyO/6VnfMfe75bp96hWfq7py7PZUcO3QS/8C
=4Gzv
-----END PGP MESSAGE-----
And finally, I am proving ownership of this host by posting or
appending to this document.
View my publicly-auditable identity here: https://keybase.io/tomalexander
==================================================================

33
static/index.html Normal file
View File

@ -0,0 +1,33 @@
<html>
<head>
<title>FizzBuzz</title>
</head>
<body>
<h1>FizzBuzz Dev Blog.</h1>
<p><strong>Coming Eventually!</strong></p>
<br/>
<p>Please check out my repos at <a href="https://code.fizz.buzz/explore/repos">code.fizz.buzz</a>.</p>
<p>
Links
</br>
<ul>
<li>My Personal Repos: <a href="https://code.fizz.buzz/explore/repos">code.fizz.buzz</a></li>
<li>LinkedIn: <a href="https://www.linkedin.com/in/tom-alexander-b6a18216/">https://www.linkedin.com/in/tom-alexander-b6a18216/</a></li>
<li>GitHub: <a href="https://github.com/tomalexander">https://github.com/tomalexander</a></li>
<li>Resume: <a href="https://fizz.buzz/resume.pdf">https://fizz.buzz/resume.pdf</a></li>
<li>PGP Key: <a href="https://fizz.buzz/pgp.asc">https://fizz.buzz/pgp.asc</a></li>
</ul>
</p>
<h3>Why is your website the way it is?</h3>
<p>I used to have a developer blog hosted at this domain. I quickly developed an appreciation for the power of org-mode for writing the content of the blog but I grew tired of inconsistent build results. The static site generators at the time would function by calling out to emacs itself to parse the org-mode and export HTML which meant that updates to emacs, my elisp packages, or the static site generator could cause compatibility issues. This often lead to things like escaping issues in old blog posts going unnoticed.</p>
<p>To solve the issue, and to seize the opportunity to gain more experience in Rust, I decided to write my own static site generator that would not depend on outside tools. So far I have written <a href="https://code.fizz.buzz/talexander/duster">the template engine</a> and I am in the process of writing <a href="https://code.fizz.buzz/talexander/organic">an org-mode parser</a>. When that is done, it should just be a matter of tying those two together with some minor glue to make a static site generator to create the new version of this site. Until that is done, I am using this hastily thrown-together manually-written html file as a placeholder.</p>
<p>That isn't to say that there are no exciting things hosted on this server, just not at the root domain. For example, this server is running kubernetes that I set up manually following <a href="https://github.com/kelseyhightower/kubernetes-the-hard-way">kubernetes-the-hard-way</a> in a bunch of <a href="https://man.freebsd.org/cgi/man.cgi?bhyve">bhyve VMs</a> that I networked together using <a href="https://man.freebsd.org/cgi/man.cgi?netgraph(4)">netgraph</a>. On it I host my own <a href="https://www.powerdns.com/">PowerDNS</a> server as the authoratative DNS server for fizz.buzz. It is integrated with <a href="https://cert-manager.io/">cert-manager</a> and <a href="https://github.com/kubernetes-sigs/external-dns">ExternalDNS</a> so Ingresses/LoadBalancers on my cluster automatically get valid TLS certificates and update the DNS records. I have a fully open-source self-hosted gitops workflow where a commit to a git repo I'm hosting in <a href="https://code.fizz.buzz/">gitea</a>, triggers a <a href="https://tekton.dev/">tekton pipeline</a> through <a href="https://github.com/jenkins-x/lighthouse">lighthouse</a> to build a docker image with <a href="https://github.com/GoogleContainerTools/kaniko">kaniko</a>, which gets pushed to my self-hosted <a href="https://goharbor.io/">harbor</a> instance, which then gets deployed to my cluster via <a href="https://fluxcd.io/">flux</a>. The end result is I make a commit to a repo and the result is deployed to my website in minutes.</p>
</body>
</html>

34
static/pgp.asc Normal file
View File

@ -0,0 +1,34 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEXZwWGhYJKwYBBAHaRw8BAQdAfv7qozKkmf4D+5PDzADsMm4aAKDGLha7+Cu0
0H+RsWG0HVRvbSBBbGV4YW5kZXIgPHRvbUBmaXp6LmJ1eno+iJAEExYIADgWIQS4
SBWTY8KHeReVS+En3kDZuEVcGwUCXZwWGgIbAwULCQgHAgYVCAkKCwIEFgIDAQIe
AQIXgAAKCRAn3kDZuEVcG9glAQDX3Bzaz9sQpycc40LeLxSKQsWplfJigfr8wWOg
C15TywEAqkTtCrTNsltdZERLMre7qnv/6RSo54OW0C4pdN7UUAa0HlRvbSBBbGV4
YW5kZXIgPHdvcmtAZml6ei5idXp6PoiQBBMWCAA4FiEEuEgVk2PCh3kXlUvhJ95A
2bhFXBsFAl+w+R0CGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQJ95A2bhF
XBt6fgD+NOYnw9gz5K/q3H5LE/JvqzCSHezJmeGgif0CuU4m1/MA+gPDKME7syEt
JsTpELEMrxWWpDW0tD/W1iJE7roGYPQPtB9Ub20gQWxleGFuZGVyIDx0b21AaGFy
bW9uaWMuYWk+iJAEExYIADgWIQS4SBWTY8KHeReVS+En3kDZuEVcGwUCX7D5RAIb
AwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAn3kDZuEVcGzjDAP9pM1ScstOk
ti+oRAsNSk8qsjIsCT9O5voDS0Q7plWlcwD/btKVFO9tPLsXhyvdB+NSwueVs7TA
kRVjlW3hktpefg24OARdnBYaEgorBgEEAZdVAQUBAQdArbTYQgDBMG7EBFTKA6+f
4CWgwl26Lf2b6cyCGfUw2j4DAQgHiHgEGBYIACAWIQS4SBWTY8KHeReVS+En3kDZ
uEVcGwUCXZwWGgIbDAAKCRAn3kDZuEVcG03MAQCrkjrE+MhtvbfGaHGHlwz9QnF0
Z519YzK8Xr8m0O+09QEA9BFCfkAzBM4D4JKeWJh/tmN9U6UexzLrRdY+W9cugAm4
MwRdnBbKFgkrBgEEAdpHDwEBB0A/IgvgQaDhPkk72raSlUPLZaMyJfPedlfBhbgY
uhNiSIj1BBgWCAAmAhsCFiEEuEgVk2PCh3kXlUvhJ95A2bhFXBsFAl+w+hYFCQe4
fcwAgXYgBBkWCAAdFiEEgeZEOZZ1UC6xJRa606F5yaU8Dt4FAl2cFsoACgkQ06F5
yaU8Dt6MngD+Krs3aYyHH6i85ebVESgBI8XeXhgACM4exepw+0UcoYkBAKK4DvV3
oJD6o1ku6Rr8pUH962SQm8PO9pO2JBBAb6ADCRAn3kDZuEVcG9uAAP43vUsbe24/
6tjEezAW0a4L2E1u4HNU8t53lolngs1kswEAy1HBdYEMR9TovX/kMeBHLcz1J2pM
VRSV0JnJhj5eZwa4MwRdnBcBFgkrBgEEAdpHDwEBB0BrvpOZa4q6JHVuc1XUVQTq
hDgLwD5SJBvzHSTXPYOZMoh+BBgWCAAmAhsgFiEEuEgVk2PCh3kXlUvhJ95A2bhF
XBsFAl+w+hYFCQe4fZUACgkQJ95A2bhFXBs3NgEA3SFYTgRVstidfoEpEZV4DdSL
kXaOwN3Eyba4UniClyMA/2CCxQt24vu19TyvUtOXWCp9Zi8SyIqoeiXQ4ZmhhnQO
uDgEXZwXKBIKKwYBBAGXVQEFAQEHQA7S3cFTEu6iROopVyF4UBl3hQrEAbOc9CW+
xXKFZYgSAwEIB4h+BBgWCAAmAhsMFiEEuEgVk2PCh3kXlUvhJ95A2bhFXBsFAl+w
+hcFCQe4fW4ACgkQJ95A2bhFXBtUXAEAyEJCUNVSJ7qvQv5IXuwbYTX2Mh7JU3+F
GJHO7AWBXCQA/2aLAi9kYmz9ba770XYwTeBZIv9Y6UIwIwVmFdYHC/EM
=a/z4
-----END PGP PUBLIC KEY BLOCK-----

BIN
static/resume.pdf Normal file

Binary file not shown.