diff --git a/package-lock.json b/package-lock.json index c787ce8..5fe8a2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "@iconify-json/mdi": "^1.2.3", "@tailwindcss/typography": "^0.5.16", "@types/node": "^22.14.0", - "npm-check-updates": "^17.1.16", + "npm-check-updates": "^17.1.18", "prettier": "^3.5.3", "prettier-plugin-astro": "^0.14.1", "prettier-plugin-tailwindcss": "^0.6.11" @@ -5930,9 +5930,9 @@ } }, "node_modules/npm-check-updates": { - "version": "17.1.16", - "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.16.tgz", - "integrity": "sha512-9nohkfjLRzLfsLVGbO34eXBejvrOOTuw5tvNammH73KEFG5XlFoi3G2TgjTExHtnrKWCbZ+mTT+dbNeSjASIPw==", + "version": "17.1.18", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.18.tgz", + "integrity": "sha512-bkUy2g4v1i+3FeUf5fXMLbxmV95eG4/sS7lYE32GrUeVgQRfQEk39gpskksFunyaxQgTIdrvYbnuNbO/pSUSqw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -7654,9 +7654,9 @@ } }, "node_modules/vite": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.4.tgz", - "integrity": "sha512-veHMSew8CcRzhL5o8ONjy8gkfmFJAd5Ac16oxBUjlwgX3Gq2Wqr+qNC3TjPIpy7TPV/KporLga5GT9HqdrCizw==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz", + "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", diff --git a/package.json b/package.json index 3f9bbb6..87fff70 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@iconify-json/mdi": "^1.2.3", "@tailwindcss/typography": "^0.5.16", "@types/node": "^22.14.0", - "npm-check-updates": "^17.1.16", + "npm-check-updates": "^17.1.18", "prettier": "^3.5.3", "prettier-plugin-astro": "^0.14.1", "prettier-plugin-tailwindcss": "^0.6.11" diff --git a/src/components/Article.astro b/src/components/Article.astro index e960167..63a0022 100644 --- a/src/components/Article.astro +++ b/src/components/Article.astro @@ -9,11 +9,6 @@ import RelatedArticles from "@components/RelatedArticles.astro"; const { article, isPost = false } = Astro.props; const { Content } = await article.render(); -let datesMatch = false; -if (article.data.date.getTime() == article.data.updated?.getTime()) { - datesMatch = true; -} - const listFormatter = new Intl.ListFormat("en-GB", { style: "long", type: "conjunction", @@ -41,7 +36,7 @@ const listFormatter = new Intl.ListFormat("en-GB", {
{ - datesMatch ? ( + !article.data.updated ? (

diff --git a/src/content/posts/website/index.mdx b/src/content/posts/website/index.mdx new file mode 100644 index 0000000..ef3753f --- /dev/null +++ b/src/content/posts/website/index.mdx @@ -0,0 +1,212 @@ +--- +title: "Website" +date: 2025-04-07 +description: "An overview of what I am using to host my digital content." +image: + url: "showcase.avif" + alt: "Website showcase" +categories: ["personal"] +tags: ["self-host", "forgejo", "docker", "vps"] +draft: true +--- + +This post will outline my workflow of using a self-hosted Forgejo instance and Actions runner to automatically deploy my personal site and any software releases, all without having to rely on another provider. + +![Website showcase](showcase.avif) + +## Steps + +### Private image access login? + +```sh +echo '' | docker login code.troylusty.com -u troy --password-stdin +``` + +```sh +echo $(htpasswd -nB user) | sed -e s/\\$/\\$\\$/g +``` + +### Aliases for updating VPS and pruning Docker + +```sh +echo 'alias dockerclean="docker system prune -a --volumes"' >> .bashrc +echo 'alias updateall="sudo apt update && sudo apt upgrade && sudo apt autoremove"' >> .bashrc +``` + +Thanks to [Tech Tales](https://tech-tales.blog/posts/2025/01-forgejo-runner-update) for the clean instructions on how to setup an Actions runner with Forgejo. + +```sh +docker compose run --rm forgejo-runner 'forgejo-runner' 'generate-config' > forgejo-runner/config.yml +``` + +Setup `container.docker_host: "unix:///var/run/docker.sock"` and `container.network: "forgejo"` and any labels such as `runner.labels: ["ubuntu-latest:docker://gitea/runner-images:ubuntu-latest"]` + +``` +docker compose run --rm -it forgejo-runner 'forgejo-runner' 'register' +``` + +Input `http://forgejo:3000` as the domain since forgejo is the container name in Docker and port 3000 is its relevant port. + +## Docker compose + +```yaml +services: + traefik: + image: traefik:latest + container_name: traefik + command: + - "--providers.docker" + - "--providers.docker.exposedbydefault=false" + - "--entryPoints.websecure.address=:443" + - "--certificatesresolvers.myresolver.acme.tlschallenge=true" + - "--certificatesresolvers.myresolver.acme.email=traefik@troylusty.com" + - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" + - "--entrypoints.web.address=:80" + - "--entrypoints.web.http.redirections.entrypoint.to=websecure" + - "--entrypoints.web.http.redirections.entrypoint.scheme=https" + - "--ping=true" + labels: + - "traefik.enable=true" + - "com.centurylinklabs.watchtower.enable=true" + - "traefik.http.middlewares.securityHeaders.headers.stsSeconds=31536000" + - "traefik.http.middlewares.securityHeaders.headers.stsIncludeSubdomains=true" + - "traefik.http.middlewares.securityHeaders.headers.frameDeny=true" + - "traefik.http.middlewares.securityHeaders.headers.contentTypeNosniff=true" + - "traefik.http.middlewares.securityHeaders.headers.contentSecurityPolicy=default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; base-uri 'none'; form-action 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests" + - "traefik.http.middlewares.securityHeaders.headers.referrerPolicy=no-referrer" + - "traefik.http.middlewares.securityHeaders.headers.permissionsPolicy=accelerometer=(), autoplay=(), camera=(), cross-origin-isolated=(), display-capture=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(), gamepad=(), hid=(), idle-detection=(), interest-cohort=(), serial=(), unload=()" + ports: + - "80:80" + - "443:443" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - letsencrypt:/letsencrypt + restart: unless-stopped + networks: + - traefik + healthcheck: + test: ["CMD", "traefik", "healthcheck", "--ping"] + depends_on: + watchtower: + condition: service_healthy + + watchtower: + image: containrrr/watchtower:latest + command: --label-enable --interval 1800 --rolling-restart --cleanup --remove-volumes + container_name: watchtower + networks: + - traefik + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /home/troy/.docker/config.json:/config.json + restart: unless-stopped + healthcheck: + test: ["CMD", "/watchtower", "--health-check"] + + personalsite: + image: code.troylusty.com/troy/troylusty.com:latest + container_name: personalsite + labels: + - "traefik.enable=true" + - "traefik.http.routers.personalsite.rule=Host(`troylusty.com`)" + - "traefik.http.routers.personalsite.entrypoints=websecure" + - "traefik.http.routers.personalsite.tls.certresolver=myresolver" + - "com.centurylinklabs.watchtower.enable=true" + - "traefik.http.routers.personalsite.middlewares=securityHeaders" + restart: unless-stopped + networks: + - traefik + depends_on: + traefik: + condition: service_healthy + + zolapress: + image: code.troylusty.com/troy/zolapress:latest + container_name: zolapress + profiles: + - donotstart + labels: + - "traefik.enable=true" + - "traefik.http.routers.zolapress.rule=Host(`edu.troylusty.com`)" + - "traefik.http.routers.zolapress.entrypoints=websecure" + - "traefik.http.routers.zolapress.tls.certresolver=myresolver" + - "com.centurylinklabs.watchtower.enable=true" + - "traefik.http.middlewares.auth.basicauth.users=troy:$$2y$$05$$fgVNzDsxXDq4co3aTh/OMOKZdLzUiM9XPEU5DXCivc9sYUZy/oq1W" + - "traefik.http.routers.zolapress.middlewares=securityHeaders, auth" + restart: unless-stopped + networks: + - traefik + depends_on: + traefik: + condition: service_healthy + + unduck: + image: code.troylusty.com/troy/unduck:latest + container_name: unduck + labels: + - "traefik.enable=true" + - "traefik.http.routers.unduck.rule=Host(`unduck.troylusty.com`)" + - "traefik.http.routers.unduck.entrypoints=websecure" + - "traefik.http.routers.unduck.tls.certresolver=myresolver" + - "com.centurylinklabs.watchtower.enable=true" + - "traefik.http.routers.unduck.middlewares=securityHeaders" + restart: unless-stopped + networks: + - traefik + depends_on: + traefik: + condition: service_healthy + + forgejo: + image: codeberg.org/forgejo/forgejo:10 + container_name: forgejo + restart: unless-stopped + networks: + - traefik + - forgejo + labels: + - "traefik.enable=true" + - "traefik.http.routers.forgejo.rule=Host(`code.troylusty.com`)" + - "traefik.http.routers.forgejo.entrypoints=websecure" + - "traefik.http.routers.forgejo.tls.certresolver=myresolver" + - "com.centurylinklabs.watchtower.enable=true" + - "traefik.http.routers.forgejo.middlewares=securityHeaders" + - "traefik.http.services.forgejo.loadbalancer.server.port=3000" + - "traefik.docker.network=traefik" + volumes: + - ./forgejo:/data + ports: + - "2222:22" + depends_on: + traefik: + condition: service_healthy + + forgejo-runner: + image: code.forgejo.org/forgejo/runner:6.0.1 + container_name: forgejo-runner + user: 0:0 + depends_on: + forgejo: + condition: service_started + networks: + - forgejo + labels: + - "com.centurylinklabs.watchtower.enable=true" + volumes: + - ./forgejo-runner:/data + - ./forgejo-runner/config.yml:/data/config.yml + - /var/run/docker.sock:/var/run/docker.sock + restart: unless-stopped + command: forgejo-runner -c /data/config.yml daemon + +networks: + traefik: + external: false + name: traefik + forgejo: + external: false + name: forgejo + +volumes: + letsencrypt: +``` diff --git a/src/content/posts/website/showcase.avif b/src/content/posts/website/showcase.avif new file mode 100644 index 0000000..395dbe2 Binary files /dev/null and b/src/content/posts/website/showcase.avif differ diff --git a/src/content/projects/3d-package-design/index.mdx b/src/content/projects/3d-package-design/index.mdx index 72fe961..bbec803 100644 --- a/src/content/projects/3d-package-design/index.mdx +++ b/src/content/projects/3d-package-design/index.mdx @@ -2,7 +2,6 @@ title: "3D Package Design" description: "3D Package Design inspired by the work of Derek Elliott." date: 2020-08-16 -updated: 2020-08-16 image: { url: "troy-lusty-3d-package-design.avif", alt: "3D package design frame" } tags: ["blender"] diff --git a/src/content/projects/a-long-way-down/index.mdx b/src/content/projects/a-long-way-down/index.mdx index 3c86478..35fd645 100644 --- a/src/content/projects/a-long-way-down/index.mdx +++ b/src/content/projects/a-long-way-down/index.mdx @@ -2,7 +2,6 @@ title: "A Long Way Down (Demo)" description: "A short, atmospheric linear adventure created for my FdA Games and Interactive Design degree." date: 2023-05-11 -updated: 2023-05-11 featured: true image: { url: "alwd-img1.avif", alt: "A Long Way Down Intro Showcase" } tags: ["unreal engine", "blender", "inkscape"] diff --git a/src/content/projects/astronaut/index.mdx b/src/content/projects/astronaut/index.mdx index e5b2ccf..f16bfcb 100644 --- a/src/content/projects/astronaut/index.mdx +++ b/src/content/projects/astronaut/index.mdx @@ -2,7 +2,6 @@ title: "Astronaut" description: "Lighting and camera test." date: 2022-03-28 -updated: 2022-03-28 image: { url: "troy-lusty-astronaut.avif", alt: "Astronaut final piece" } tags: ["blender", "davinci resolve"] categories: ["personal"] diff --git a/src/content/projects/digital-artifact-corridor/index.mdx b/src/content/projects/digital-artifact-corridor/index.mdx index 25bca68..4ef864d 100644 --- a/src/content/projects/digital-artifact-corridor/index.mdx +++ b/src/content/projects/digital-artifact-corridor/index.mdx @@ -2,7 +2,6 @@ title: "Digital Artefact: Corridor (Incomplete)" description: "A virtual production horror environment made in Unreal Engine 5 and inspired by The Shining." date: 2023-01-20 -updated: 2023-01-20 image: { url: "troy-lusty-highresscreenshot05012023-2.avif", diff --git a/src/content/projects/discord-bot/index.mdx b/src/content/projects/discord-bot/index.mdx index 03cf498..4ce312d 100644 --- a/src/content/projects/discord-bot/index.mdx +++ b/src/content/projects/discord-bot/index.mdx @@ -2,7 +2,6 @@ title: "Discord Bot" description: "AQA Computer Science NEA project based around creating a Discord bot." date: 2020-03-31 -updated: 2020-03-31 image: { url: "discord.avif", alt: "Discord bot" } tags: ["python"] categories: ["education"] diff --git a/src/content/projects/firespline/index.mdx b/src/content/projects/firespline/index.mdx index a2de24f..442283e 100644 --- a/src/content/projects/firespline/index.mdx +++ b/src/content/projects/firespline/index.mdx @@ -2,7 +2,6 @@ title: "Firespline" description: "A fire animation test presented in a small cave scene." date: 2022-01-06 -updated: 2022-01-06 image: { url: "troy-lusty-firespline.avif", alt: "Firespline frame" } tags: ["blender", "davinci resolve"] categories: ["personal"] diff --git a/src/content/projects/kraken-in-the-cupboard/index.mdx b/src/content/projects/kraken-in-the-cupboard/index.mdx index 490104d..6d24378 100644 --- a/src/content/projects/kraken-in-the-cupboard/index.mdx +++ b/src/content/projects/kraken-in-the-cupboard/index.mdx @@ -2,7 +2,6 @@ title: "Kraken in the Cupboard" description: "Mythical depiction of the Kraken bursting its way out of a bookcase cupboard." date: 2021-12-11 -updated: 2021-12-11 image: { url: "troy-lusty-kraken.avif", alt: "Kraken in the Cupboard final" } tags: ["blender"] categories: ["personal"] diff --git a/src/content/projects/logofolio/index.mdx b/src/content/projects/logofolio/index.mdx index 20c72bc..8ebe0a4 100644 --- a/src/content/projects/logofolio/index.mdx +++ b/src/content/projects/logofolio/index.mdx @@ -2,7 +2,6 @@ title: "Logofolio" description: "An ongoing collection of branding and logos designs." date: 2021-06-16 -updated: 2021-06-16 image: { url: "troy-lusty-logofolio.avif", alt: "Logofolio title" } collection: true tags: ["blender", "pixelmator", "affinity photo", "affinity designer"] diff --git a/src/content/projects/megascans-artworks/index.mdx b/src/content/projects/megascans-artworks/index.mdx index 440579f..5a3101d 100644 --- a/src/content/projects/megascans-artworks/index.mdx +++ b/src/content/projects/megascans-artworks/index.mdx @@ -2,7 +2,6 @@ title: "Megascans Artworks" description: "A small collection of artworks made with Megascans assets." date: 2021-01-29 -updated: 2021-01-29 collection: true image: { url: "troy-lusty-forest-fire.avif", alt: "Forest fire" } tags: ["quixel megascans", "blender"] diff --git a/src/content/projects/mortis/index.mdx b/src/content/projects/mortis/index.mdx index 570910e..88fd43f 100644 --- a/src/content/projects/mortis/index.mdx +++ b/src/content/projects/mortis/index.mdx @@ -2,7 +2,6 @@ title: "Mortis" description: "1 Corinthians 15:26 - The last enemy to be destroyed is death." date: 2022-12-10 -updated: 2022-12-10 image: { url: "troy-lusty-mortis.avif", diff --git a/src/content/projects/nightmare/index.mdx b/src/content/projects/nightmare/index.mdx index 4da5b73..dc10b00 100644 --- a/src/content/projects/nightmare/index.mdx +++ b/src/content/projects/nightmare/index.mdx @@ -2,7 +2,6 @@ title: "Nightmare" description: "Little Nightmares inspired game demo and environment completed for my college final major project." date: 2021-04-21 -updated: 2021-04-21 image: { url: "troy-lusty-nightmare.avif", alt: "Nightmare Frame 0600" } tags: ["unreal engine", "blender", "davinci resolve", "photoshop", "zbrush"] categories: ["education"] diff --git a/src/content/projects/packard/index.mdx b/src/content/projects/packard/index.mdx index 33ece49..ffdd74e 100644 --- a/src/content/projects/packard/index.mdx +++ b/src/content/projects/packard/index.mdx @@ -2,7 +2,6 @@ title: "Packard" description: "A simple RSS aggregator meant to allow you to take a quick glance at what's occurring in topics you care about." date: 2025-01-12 -updated: 2025-01-12 image: { url: "packard.avif", alt: "Packard GitHub v0.0.1 Release" } tags: ["rust", "rss aggregator"] categories: ["personal"] diff --git a/src/content/projects/pasikdhar/index.mdx b/src/content/projects/pasikdhar/index.mdx index 2b13ded..dac309d 100644 --- a/src/content/projects/pasikdhar/index.mdx +++ b/src/content/projects/pasikdhar/index.mdx @@ -2,7 +2,6 @@ title: "Pasikdhar" description: "Depiction of the staircase in my home being haunted by a night terror." date: 2023-07-25 -updated: 2023-07-25 image: { url: "troy-lusty-pasikdhar-final.avif", diff --git a/src/content/projects/sixth-form-artworks/index.mdx b/src/content/projects/sixth-form-artworks/index.mdx index c49a4ed..3bc69ea 100644 --- a/src/content/projects/sixth-form-artworks/index.mdx +++ b/src/content/projects/sixth-form-artworks/index.mdx @@ -2,7 +2,6 @@ title: "Sixth Form Artworks" description: "Assorted artwork completed in my time at sixth form." date: 2020-02-21 -updated: 2020-02-21 collection: true image: { diff --git a/src/content/projects/studying-spider/index.mdx b/src/content/projects/studying-spider/index.mdx index 34d7efe..6619a34 100644 --- a/src/content/projects/studying-spider/index.mdx +++ b/src/content/projects/studying-spider/index.mdx @@ -2,7 +2,6 @@ title: "Studying Spider" description: "A smart little spider made within a couple lessons at college." date: 2022-01-27 -updated: 2022-01-27 image: { url: "troy-lusty-studying-spider.avif", alt: "Studying Spider" } tags: ["blender"] categories: ["personal"] diff --git a/src/content/projects/terrys-mango-juice-n-stuff/index.mdx b/src/content/projects/terrys-mango-juice-n-stuff/index.mdx index 24c91c2..f63d197 100644 --- a/src/content/projects/terrys-mango-juice-n-stuff/index.mdx +++ b/src/content/projects/terrys-mango-juice-n-stuff/index.mdx @@ -2,7 +2,6 @@ title: "Terry's Mango Juice 'N' Stuff" description: "Themed mango juice render done to test combining 3D product rendering with 2D packaging work." date: 2021-09-10 -updated: 2021-09-10 image: { url: "troy-lusty-terrys-mango.avif", diff --git a/src/content/projects/the-batman/index.mdx b/src/content/projects/the-batman/index.mdx index 59dfe2d..004f5a8 100644 --- a/src/content/projects/the-batman/index.mdx +++ b/src/content/projects/the-batman/index.mdx @@ -2,7 +2,6 @@ title: "The Batman" description: "The Bat and The Cat Trailer Shot Remake in Unreal Engine 5 & DaVinci Resolve." date: 2022-06-13 -updated: 2022-06-13 featured: true image: { url: "troy-lusty-batman.avif", alt: "Frame from the final video" } tags: diff --git a/src/content/projects/tomb/index.mdx b/src/content/projects/tomb/index.mdx index 43e7217..5ca9810 100644 --- a/src/content/projects/tomb/index.mdx +++ b/src/content/projects/tomb/index.mdx @@ -2,7 +2,6 @@ title: "Tomb" description: "A moody sacrifice scene taking place in a tomb created to test SSGI in Blender Eevee." date: 2021-07-14 -updated: 2021-07-14 image: { url: "troy-lusty-tomb.avif", alt: "Tomb final" } tags: ["blender", "affinity photo"] categories: ["personal"] diff --git a/src/content/projects/untitledarmy-inspired-character/index.mdx b/src/content/projects/untitledarmy-inspired-character/index.mdx index 2521bae..45da993 100644 --- a/src/content/projects/untitledarmy-inspired-character/index.mdx +++ b/src/content/projects/untitledarmy-inspired-character/index.mdx @@ -2,7 +2,6 @@ title: "UntitledArmy Inspired Character" description: "A stylised character design inspired by the work of UntitledArmy." date: 2022-01-22 -updated: 2022-01-22 image: { url: "troy-lusty-untitledarmy.avif", diff --git a/src/content/projects/webboss/index.mdx b/src/content/projects/webboss/index.mdx index 0102ef3..36e5b48 100644 --- a/src/content/projects/webboss/index.mdx +++ b/src/content/projects/webboss/index.mdx @@ -2,7 +2,6 @@ title: "WebBoss (Work experience)" description: "Designs created for WebBoss as part of my work experience in sixth form." date: 2019-06-15 -updated: 2019-06-15 image: { url: "swimboss.avif", alt: "WebBoss SwimBoss" } tags: ["adobe xd", "adobe photoshop"] categories: ["client work"] diff --git a/src/icons/cat.svg b/src/icons/cat.svg new file mode 100644 index 0000000..a3e116a --- /dev/null +++ b/src/icons/cat.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/layouts/Cv.astro b/src/layouts/Cv.astro index f54aaff..f6137df 100644 --- a/src/layouts/Cv.astro +++ b/src/layouts/Cv.astro @@ -11,10 +11,10 @@ import icon from "public/assets/icon.png";

- {CV.TITLE}{CV.DESCRIPTION}{CV.TITLE}{CV.DESCRIPTION}

Digital designer.