Doel
In vorige post implementeerde ik verschillende logische servers op mijn proxmox home-server machine:
“templ-ubuntu”, “home-devdepserver” en “home-utilityserver”.
Zie Architecture of my home server
.
Ik wil nu een eerste minimale demonstratie web-applicatie in Golang met een MariaDB database ontwikkelen,
gebruikmakend van de centrale repository voor source code opslag.
De applicatie dient daarna als OCI container opgeleverd te worden en in de centrale registry voor binaries opgeslagen te worden.
Daarna dient een applicatie-execution server-omgeving op mijn home-server aangemaakt te worden.
De aangemaakte containerized applicatie en database dient op deze server-omgeving vervolgens gedeployed te worden.
Hiervoor zal ik “home-testappserver” en “home-prodappserver” als logische servers installeren.
Als laatste wil ik deze gedeployde web-applicatie publiek toegankelijk maken via tunneling.
De applicatie moet kunnen opgeroepen worden via een link in de “Demo” pagina van mijn website op Cloudflare.
In deze post wil ik hiervoor mijn “virtueel datacenter” vervolledigen met communicatie middleware.
Het opruimen van bestaande “home-pve” en “home-backupserver” zal later volgen.
Na deze post krijgen we dan volgende situatie:
Met dit project werk ik de realisatie van al mijn ideeën voor de publieke website en een klein virtueel datacenter volledig af.
In volgend project wil ik starten met de verdere uitwerking van mijn ideeën over een moderne software-fabriek:
applicatie development tools, testing, security, CI/CD, OCI & Kubernetes en app/infra-monitoring.
Resultaat
1 - Aankoop en installatie van laptop
Ik kocht mijn eerste laptop en installeerde er Linux Mint als OS op.
Ik koos voor een gereviseerde business laptop, die geschikt is voor web development, aan een budget prijs.
Zie Architecture of my laptop
.
Deze Linux Laptop gebruikte ik om alle nieuwe software uit te testen en aan te leren.
In de toekomst ga ik volledig overstappen van Windows desktops naar enkel Linux desktops.
2 - Beveiliging van thuis-netwerk, servers, werkstations en software
Omdat ik applicaties in mijn thuisnetwerk toegankelijk wil maken vanuit het internet,
dien ik de toegang tot lokale resources beter te beveiligen.
Bezoekers bij mij thuis geef ik ook toegang tot mijn wifi-netwerk,
en ik wil hier tevens voorkomen dat deze toegang krijgen tot andere lokale resources dan het internet.
Ik bouwde daarom mijn toegangsbeveiliging uit en dit gebeurde op verschillende niveau’s.
Op netwerk-niveau probeerde ik firewall’s op routers en VLAN’s (virtuele LAN) te gebruiken.
Door gescheiden virtuele netwerken op 1 fysiek netwerk te voorzien,
kan ik internet bezoekers en wifi bezoekers thuis gescheiden houden van interne gebruikers.
Ik gebruik echter een router geleverd door mijn ISP die geen VLAN’s ondersteunt,
en dien daarom te wachten op een upgrade van mijn ISP.
De firewall-regels op mijn router laten nu alle uitgaand verkeer naar het internet toe,
maar blokkeren alle inkomend verkeer (dit zal ik later in deze post heel beperkt moeten wijzigen).
Op machine/OS-niveau heb ik voor alle machines firewall’s geinstalleerd en geconfigureerd.
Op mijn Windows desktop is dit de ingebouwde Windows firewall,
en op mijn Linux Mint laptop is dit de UFW firewall software.
Deze workstations laten alle uitgaand verkeer toe, maar blokkeren alle inkomend verkeer bij default.
Op mijn NAS/home-server werd proxmox als hypervisor OS geinstalleerd en die voorziet in een hierarchy van firewall’s.
Proxmox implementeert software-matig op de machine een eigen intern netwerk met een virtuele switch,
die alle lxc’s en vm’s verbindt met het home netwerk.
Op het node-niveau en elk lxc/vm-niveau voorziet proxmox een aparte firewall die geconfigureerd dient te worden.
Zie “Network and Firewall organization” sectie in Architecture of my home server .
Beveiliging voor iedere toegankelijke service/applicatie dient ook voorzien te worden.
Voor de ssh-service en gitea server software werd reeds beveiliging via ssh-keys geimplementeerd.
Desktop en Laptop workstation beschikken daarom over mijn persoonlijke private ssh-key,
en alle servers beschikken over mijn persoonlijke public ssh-key om gemakkelijk toegang te verlenen.
Voor zelfontwikkelde applicaties die publiek toegangelijk zijn,
voorzie ik enkel beveiligde https of vpn toegang na (paswoord) authenticatie door de gebruiker.
Meer uitleg over de gekozen authenticatie-software volgt later in deze post.
3 - Ontwikkeling van minimale demo web-applicaties in Go
3.1 - Ontwikkel demo_hello applicatie
Als eerste maakte ik een HelloWorld applicatie “demo_hello” aan in Golang (met prefix “example-” in Gitea).
Voor de implementatie werd de standaard net/http en html/template library in go gebruikt.
Ik koos Golang als programmeertaal omdat het een eenvoudige, performante taal is,
en echt geschikt om in containers/cloud te draaien.
Deze HelloWorld repo kan hierna gebruikt worden om de development van alle nieuwe golang projecten gemakkelijk te kunnen opstarten.
De repo bevat de te gebruiken github/gitea configuraties, local git configuraties, en de golang setup.
Het bevat ook een eenvoudige makefile om een compile, linter-ing en test workflow door automatisatie te vereenvoudigen.
Later zal ook andere pipeline-logica toegevoegd worden.
Op deze manier werd onmiddelijk bij de start een goede development workflow afgedwongen.
Zie Golang by example - 01
voor meer uitleg.
Deze en alle volgende repositories voor applicatie-development zijn publiek toegankelijk in mijn GitHub / RobertTC32 account.
3.2 - Ontwikkel demo_todo applicatie
Daarna werd de “demo_todo” repo (met prefix “app-” in Gitea) aangemaakt met demo_hello repo als starter.
De repo-structuur werd voorzien om niet enkel golang source code te bevatten,
maar ook golang test code, sql script files, pipeline specificaties, etc.
Vervolgens heb ik dan een mariadb database aangemaakt met sql scripts voor creatie van db-objecten en testdata.
MariaDB is een razendsnel, open-source en erg populair relationeel databasebeheersysteem (RDBMS).
Het is een directe ‘fork’ van MySQL, opgezet door de oorspronkelijke ontwikkelaars.
Een mariadb database zal ik in latere projecten ook in kubernetes gebruiken (met horizontal scaling en backup),
en er dan performantietesten op uitvoeren.
Na de aanmaak van de databank werd een eerste versie van de demo_todo web applicatie ontwikkeld.
Deze toonde enkel de database-inhoud als todo-rijen in een tabel op het scherm.
3.3 - Deploy containerized web-applicaties op applicatie-server
Voor beide web applicaties maakte ik een zo klein mogelijke OCI-image,
en installeerde deze daarna op mijn test- en prod- applicatie servers.
Door een upgrade van Windows werkte plots “Docker” en “Docker Desktop” niet meer.
Ik heb dan “Podman Desktop” op mijn Windows desktop geïnstalleerd en uitgetest.
Na heel wat uittesten kon ik het probleem met docker ook oplossen.
Containerizatie en deployment gebeurden handmatig,
maar in volgende posts zullen we dit automatiseren (ansible).
Na het opstarten op de applicatie-servers, werden de web applicaties uitgetest binnen het thuisnetwerk.
4 - Maak web-applicatie publiek toegankelijk via tunneling
4.1 - Maak demo_todo applicatie toegankelijk
De ToDo web-applicatie is gehost in mijn thuis-netwerk en niet zonder meer toegankelijk over het internet.
Om publieke toegang te voorzien, heb ik eerst veel bijgeleerd over networking en hiervan een overzicht gemaakt.
Zie Overview of network technology
voor meer uitleg.
In dit overzicht vind je:
- Netwerk-technologieën
- Netwerk-middleware om websites en web applicaties te ondersteunen
- Producten om vanuit internet toegang te hebben tot applicaties in je thuis-netwerk
Ik koos er uiteindelijk voor om gebruik te maken van Cloudflare Tunneling,
omdat ik al beschikte over een domein-naam en een (gratis) Cloudflare account.
Ik diende dus enkel nog een Cloudflare connector “cloudflared” aan te maken en te configureren in mijn LAN.
De connector installeerde ik als service op de ubuntu app server (installatie als docker container gaf problemen).
Tijdens de installatie werd echter vereist dat ik een kredietkaart toevoegde.
Het gebruik is volledig gratis maar het verplicht registreren van een kredietkaart is voor mij toch een minpunt.
Mijn ToDo applicatie is nu bereikbaar via mijn publieke website op Cloudflare.
In deze sectie installeerde ik dus software Cloudflared als agent op “home-prodappserver”.
Na deze installatie is de demo_todo applicatie toegankelijk via de “Demo” tab van deze website
of rechtstreeks via demo-todo
.
4.2 - Vervolledig implementatie van demo_todo applicatie
De implementatie van de web gui werd ge-refactor-ed om voortaan de templ tool (vs Chi, Gin, Fiber, Echo) te gebruiken.
Voor de web presentatie gebruikte ik de reeds gekende tailwind css technologie.
Zie Golang by example - 02
voor meer uitleg.
Voor de toegang tot de databank gebruikte ik de sqlx package,
die zorgt voor een eenvoudigere mapping en foutafhandeling voor de database-toegangscode in Golang.
Ik koos ervoor om geen ORM (zoals gorm) of code-generatietool (zoals sqlc) te gebruiken.
Als laatste werden web-schermen aangemaakt om een todo-lijn toe te voegen, te verwijderen, of todo-details te wijzigen.
Hiervoor maakte ik gebruik van Htmx (vs AlpineAjax), DaisyUI (vs Shadcn UI, Tailwind UI)
en later AlpineJs (vs Datastar) als extra frontend-technologieën.
Htmx is een kleine Javascript library die nieuwe attributes aan bestaande HTML elementen toevoegt.
Hiermee kan code voor communicatie met backend server in de browser uitgevoerd worden zonder javascript programmatie.
DaisyUI is een UI componenten bibliotheek volledig gebaseerd op Tailwind css,
die toelaat om sneller mooiere web interfaces te maken.
4.3 - Refactor de architectuur van demo_todo applicatie
Vooreerst heb ik de huidige belangrijkste applicatie architecturen bestudeerd:
“Traditional Layered Architecture”, “Vertical Slice Architecture”, “Hexagonal Architecture”, “Onion Architecture” en “Clean Architecture”.
Voor iedere architectuurtype heb ik de opbouw, terminologie, bestaansredenen, voor- en nadelen en implementatie-wijze bekeken.
Dit kostte me heel wat tijd en moeite.
De volledige demo_todo applicatie werd daarna geherstructureerd naar een “Hexagonal Architecture”,
om testing en onderhoud achteraf gemakkelijker te maken.
Ook werd een heel eenvoudige REST API als applicatie-toegang toegevoegd, om deze architectuur beter te kunnen uitproberen.
Voor de definitie van port interfaces werden ook “Data Transfer Objects” (DTO) gebruikt.
Error handling is niet zo eenvoudig in een web applicatie:
- methodes in de verschillende ports (van de Hexagonal Architecture) kunnen errors teruggeven,
en dienen goed georganiseerd te worden. - sommige van deze errors zijn specifiek en vereisen een speciale afhandeling (bv tonen op het scherm);
andere errors vereisen dit niet. - errors in de ui laag moeten op een correcte manier via http doorgegeven worden naar de web pagina in de browser
Dit alles vergde heel wat experimenteren om een voorlopig voldoende elegante implementatie te vinden.
4.4 - Voeg CDN toe aan demo_todo applicatie
Voor het ophalen van static web resources voor web applicaties kan gebruik gemaakt worden van de CDN functionaliteit van Cloudflare.
Hierdoor kan dit veel efficienter en on the Edge gebeuren.
Voor de ToDo applicatie gebruikte ik daarom deze CDN mogelijklheid om de gebruikte javascript files,
voor htmx, htmx-ext-response-targets en alpinejs (samen ongeveer 100 KB) op mijn persoonlijke cdn op cloudflare beschikbaar te stellen.
De URL van mijn persoonlijk beheerde CDN is “https://cdn.robertthecoder.org”.
Hierdoor zijn deze files sneller beschikbaar bij de opladen, maar is ook de docker image van mijn applicatie kleiner.
Dit resulteert in volgende architectuur:
Dit plaatje werd gemaakt met “Mermaid” software.
Ik gebruikte hiervoor “Markdown Preview Mermaid Support” en “markdownlint” als VSCode extensies.
In vorige projecten gebruikte ik reeds “PlantUML” en “Drawio” in VSCode om diagramma’s aan te maken.
Mermaid kan enkel eenvoudigere diagram’s dan PlantUML aanmaken,
maar de renderer is standaard reeds voorzien in GitLab, GitHub en Gitea.
5 - Maak web-applicaties publiek toegankelijk zonder tunneling
5.1 - Installeer port forwarding en dynamic DNS
Ik ga later ook meerdere zelf-gehoste web applicaties publiek maken zonder tunneling.
Ik configureerde hiertoe port forwarding op mijn ISP router,
zodat externe http(s) requests worden doorgegeven naar mijn gedeployde demo_hello applicatie op mijn applicatie server.
Dit vereist wel een statisch publiek IP-adres, wat ik als gewone internet gebruiker niet kreeg van mijn ISP (Telenet).
Ik loste dit op door gebruik te maken van “Dynamic DNS” (DDNS) die door mijn DNS Registrar (Cloudflare) wordt ondersteund.
Op mijn proxmoc machine installeerde ik Cloudflare-DDNS software,
die ik ieder uur mijn extern IP adres van thuis laat doorgeven aan Cloudflare.
Speciale subdomein van mijn DNS naam (als A DNS records, namelijk “app-demo-hello.robertthecoder.org”,
wordt zo gemapt en up-to-date gehouden, met mijn publiek ip-adres thuis.
Door ook gebruik te maken van Cloudflare als proxy kan ik mijn eigen publiek IP-adres verborgen houden.
Dit resulteert dan in bovenstaande architectuur.
5.2 - Installeer reverse proxy en HTTPS support
Later wil ik meerdere zelf-gehoste web applicaties publiek maken met https toegang en zonder tunneling.
Hiertoe installeerde ik Caddy als lichtgewicht reverse proxy (vs Traefik, Nginx).
Ik wijzigde de port forwarding op mijn router zodat http en https requests doorgegeven worden naar deze reverse proxy.
Deze reverse proxy zal de https request omvormen naar een http request,
en forwarden naar mijn zelf-gehoste demo_hello en andere web applicaties.
Het gebruik van https vereist ook een geldig SSL certificaat.
Caddy zorgt hier automatisch voor (met ‘Let’s Encrypt’) bij directe toegang.
Voor toegang via cloudflare kan dit via DNS Challenge tussen de reverse proxy en Cloudflare.
Caddy als reverse proxy ondersteunt deze DNS Challenge handshake na installatie van een extra cloudflare module.
Na deze installatie is de demo_hello applicatie toegankelijk via de “Demo” tab van deze website,
of hier via demo_hello
.
Op dezelfde wijze zal ik naast demo_hello ook andere zelf-gehoste web applicaties in de toekomst publiek bereikbaar maken.
6 - Voeg toegangsbeveiliging toe aan web-applicaties
6.1 - Installeer authenticatie en authorisatie middleware
Ik heb gekozen voor Authelia (in plaats van Microsoft ADFS, Keycloak en Authentik), een gratis en open-source OpenID Connect 1.0-provider.
Het is een lichtgewicht, snelle en veilige oplossing voor authenticatie en autorisatie van webapplicaties,
door middel van twee-factor-authenticatie en single sign-on (SSO) voor web applicaties.
Het fungeert als aanvulling op reverse proxies (zoals Caddy) door verzoeken toe te staan, te weigeren of door te sturen.
Ik heb de Authelia-software geïnstalleerd naast Homarr in de Linux-container “home-utilityserver”.
Vervolgens heb ik Authelia geïntegreerd in mijn Caddy reverse proxy-configuratie.
6.2 - Voeg gebruikers-authenticatie en authorisatie toe aan demo_hello applicatie
