3.6 KiB
Executable File
3.6 KiB
Executable File
Monotrope
Personal blog and server infrastructure for monotrope.au.
Project Structure
monotrope/
site/ # Hugo site (content, templates, config)
infra/ # Server setup scripts and config files
deploy.sh # Build + rsync to production
Makefile # Common tasks
Tech Stack
- Static site generator: Hugo
- Web server: Caddy (automatic HTTPS via Let's Encrypt)
- Hosting: DigitalOcean droplet (Sydney region, Ubuntu 24.04 LTS)
- Deployment:
hugo buildthenrsyncto server - Future services: Docker Compose for anything beyond the blog
Setup Tasks
1. Initialise the repo
- Create the directory structure above
git initwith a sensible.gitignore(Hugo output dirpublic/,.env, etc.)- Initialise a new Hugo site inside
site/ - Use a minimal theme or no theme — we'll build templates from scratch later
- Hugo config should set
baseURL = "https://monotrope.au"
2. Create a minimal Hugo site
- A single layout (
layouts/_default/baseof.html,single.html,list.html) - Minimal, clean CSS — no framework. Readable prose typography, dark mode support via
prefers-color-scheme - A sample first post in
site/content/posts/so we can test the build - RSS feed enabled (Hugo does this by default)
- No JavaScript unless strictly necessary
3. Server provisioning script
Create infra/setup.sh — a bash script intended to be run once on a fresh Ubuntu 24.04 droplet via SSH. It should:
- Update packages
- Install Caddy via the official apt repo
- Create a
wwwuser with no login shell to own the site files - Create
/var/www/monotropeowned bywww - Install a Caddyfile at
/etc/caddy/Caddyfilethat:- Serves
monotrope.aufrom/var/www/monotrope - Enables gzip/zstd compression
- Sets sensible cache headers for static assets
- Handles
www.monotrope.auredirect to apex
- Serves
- Enable and start the Caddy service
- Set up UFW: allow SSH, HTTP, HTTPS, deny everything else
- Install Docker and Docker Compose (for future use, not needed yet)
- Create a deploy user with SSH key auth and permission to write to
/var/www/monotrope
Also create infra/Caddyfile as a standalone config file that the setup script copies into place.
4. Deploy script
Create deploy.sh at the repo root:
- Run
hugo --minifyinsite/ rsync -avz --delete site/public/ deploy@<DROPLET_IP>:/var/www/monotrope/- Print the URL on success
The droplet IP should come from an environment variable MONOTROPE_HOST or a .env file (not committed).
5. Makefile
Targets:
make build— build the site locallymake serve—hugo serverfor local dev with live reloadmake deploy— rundeploy.shmake ssh— SSH into the droplet as the deploy usermake setup— run the provisioning script on a fresh droplet
Conventions
- All shell scripts should use
set -euo pipefail - Prefer clarity over cleverness in all scripts
- No unnecessary dependencies — this should stay simple
- Australian English in all content and comments
- Markdown content lives in
site/content/; one subdirectory per content type (e.g.posts/,pages/)
DNS
The user will configure DNS separately via their registrar. The server expects:
monotrope.au→ droplet IP (A record)www.monotrope.au→ droplet IP (A record)
Caddy will handle certificate provisioning automatically once DNS is pointed.
What This Is Not
- No CI/CD pipeline — deploy is manual via
make deploy - No containerisation of the blog itself — it's static files
- No database
- No analytics (for now)
- No comments system (for now)