From 12e61a8d758ed2d0d088b0e87abe33b84a8cf0ae Mon Sep 17 00:00:00 2001 From: patrick Date: Sat, 11 Apr 2026 07:56:51 -0400 Subject: [PATCH] update blog posts with alerts and editorial improvements --- .../blog/build-your-own-adblocker/index.mdx | 9 ++- .../gitea-cloudflare-deployment/index.mdx | 59 ++++++++++++++++--- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/content/blog/build-your-own-adblocker/index.mdx b/src/content/blog/build-your-own-adblocker/index.mdx index df97294..ab57e5e 100644 --- a/src/content/blog/build-your-own-adblocker/index.mdx +++ b/src/content/blog/build-your-own-adblocker/index.mdx @@ -18,6 +18,7 @@ What if you could block ads and trackers across your entire network, on every de That's what we'll build in this guide. There are already a few [ready-made solutions](#part-11-where-to-go-from-here---pi-hole-and-adguard-home), but building a simple system ourselves will help us understand how the underlying logic actually works. By the end, you'll have a working network-level ad-blocker running on a Debian machine, and a solid understanding of the DNS system that makes it all possible. +> [!IMPORTANT] > **Prerequisites**: A machine running Debian (this guide uses Debian 13 Trixie), basic comfort with the terminal, and a home network you control. You could also follow along up to Part 5 on Windows or Mac. --- @@ -106,6 +107,7 @@ Add a line like this to your hosts file: 0.0.0.0 facebook.com ``` +> [!NOTE] > If your network uses IPv6, you may also need to add the line `:: facebook.com` to block the IPv6 address. `::` is the IPv6 equivalent of `0.0.0.0`. We'll assume we're on an IPv4 network for the remainder of this post. Save the file and try it: @@ -116,11 +118,13 @@ curl -I facebook.com You should see a "connection refused" error, which is exactly what we want. The address resolves to `0.0.0.0`, nothing is listening there, and the connection fails. Alternatively, try visiting `facebook.com` in your browser — you'll get an error page instead of the site. -> **Note:** This same mechanism is what makes DNS poisoning attacks possible. If an attacker can modify your hosts file or intercept your DNS queries, they can redirect `facebook.com` to a malicious server that looks identical to the real thing. This is one reason why HTTPS and certificate validation matter: even if DNS is compromised, a valid TLS certificate is hard to fake. +> [!WARNING] +> This same mechanism is what makes DNS poisoning attacks possible. If an attacker can modify your hosts file or intercept your DNS queries, they can redirect `facebook.com` to a malicious server that looks identical to the real thing. This is one reason why HTTPS and certificate validation matter: even if DNS is compromised, a valid TLS certificate is hard to fake. Remove the `facebook.com` line when you're done experimenting. -> **Note:** You may notice that pinging `0.0.0.0` actually reaches the loopback address `127.0.0.1`. This is because RFC 1122 specifies that `0.0.0.0` is only valid as a source address. On most Unix-like systems, using it as a destination causes the OS to treat it as the local loopback instead. Keep this in mind if you have a local web server running, as it may respond to requests directed at these blocked domains. +> [!NOTE] +> You may notice that pinging `0.0.0.0` actually reaches the loopback address `127.0.0.1`. This is because RFC 1122 specifies that `0.0.0.0` is only valid as a source address. On most Unix-like systems, using it as a destination causes the OS to treat it as the local loopback instead. Keep this in mind if you have a local web server running, as it may respond to requests directed at these blocked domains. --- ## Part 4: Using the Hosts File to Block Ads @@ -240,6 +244,7 @@ bogus-priv addn-hosts=/etc/hosts.blocklist ``` +> [!TIP] > **Find your interface name** with `ip link`. It's usually `eth0` for wired connections, but modern Debian systems often use names like `enp3s0` or `ens3`. ### Restarting dnsmasq diff --git a/src/content/blog/gitea-cloudflare-deployment/index.mdx b/src/content/blog/gitea-cloudflare-deployment/index.mdx index f158952..dfea31e 100644 --- a/src/content/blog/gitea-cloudflare-deployment/index.mdx +++ b/src/content/blog/gitea-cloudflare-deployment/index.mdx @@ -2,6 +2,7 @@ title: "Deploying to Cloudflare Pages with GitHub Actions" description: "A simple CI/CD workflow for deploying static site to Cloudflare Pages using GitHub Actions" date: 2026-03-26 +updatedDate: tags: ['CI/CD', 'Gitea', 'Cloudflare Pages', 'DevOps'] authors: - "Patrick Jaroszewski" @@ -16,9 +17,20 @@ This post walks through the workflow I use to deploy this site and others I host --- +## Prerequisites + +Before getting started, you'll need: + +- A Gitea instance with Actions enabled ([documentation](https://docs.gitea.com/usage/actions/overview)) +- A registered Gitea runner (ubuntu-latest or equivalent) +- A Cloudflare account with access to Pages +- Your project set up with pnpm (adjust commands for npm/yarn as needed) + +--- + ## The Basic Workflow -Here's a minimal Gitea Actions workflow that builds an Astro site and deploys it to Cloudflare Pages: +Here's a minimal Gitea Actions workflow that builds an Astro site and deploys it to Cloudflare Pages. Note that Gitea uses `.gitea/workflows/` instead of GitHub's `.github/workflows/`. ```yaml title=".gitea/workflows/deploy.yaml" name: Generate a build and push to Cloudflare Pages @@ -64,6 +76,21 @@ jobs: The workflow triggers on pushes to `main`, installs dependencies, builds the site, and deploys using Cloudflare's Wrangler action. Every push to main goes straight to production. +> [!NOTE] +> Adjust `./dist` to match your framework's output directory—this is Astro's default. For example, Next.js static exports use `out`. + +--- + +## Required Secrets + +> [!TIP] +> If your Cloudflare Pages project doesn't exist yet, Wrangler will create it automatically on the first deployment. + +You'll need to configure two secrets in your Gitea repository (Settings → Actions → Secrets): + +- `CLOUDFLARE_API_TOKEN` — Create this in the Cloudflare dashboard: Profile → API Tokens → Create Token → Use the "Edit Cloudflare Pages" template (or create a custom token with **Account: Cloudflare Pages: Edit** permission) +- `CLOUDFLARE_ACCOUNT_ID` — Found in the Cloudflare dashboard sidebar under **Workers & Pages → Overview**, or in the URL when viewing any Pages project (`dash.cloudflare.com//pages`) + --- ## Using a Separate Production Branch @@ -89,12 +116,12 @@ Then add a script to promote `main` to `prod` when you're ready: ```json title="package.json" { "scripts": { - "deploy": "git push origin main:prod" + "push:prod": "git push origin main:prod" } } ``` -Now you develop freely on `main`, and run `pnpm deploy` when you want to go live. +Now you develop freely on `main`, and run `pnpm push:prod` when you want to go live. --- @@ -103,7 +130,7 @@ Now you develop freely on `main`, and run `pnpm deploy` when you want to go live If you use a `prod` branch, there's a catch: Cloudflare Pages uses the **branch name** to determine the deployment environment. - `main` or `master` → production deployment (your primary URL) -- Any other branch → preview deployment (e.g., `prod.your-project.pages.dev`) +- Any other branch → preview deployment (e.g., `branch-name.your-project.pages.dev`) If you deploy from a branch called `prod`, Cloudflare treats it as a preview deployment, not production. Your site ends up at a subdomain instead of your main URL. @@ -121,12 +148,28 @@ Option 1 is cleaner because it aligns Cloudflare's understanding with your actua --- -## Required Secrets +## Using a Preview Branch -You'll need to configure two secrets in your Gitea repository (Settings → Actions → Secrets): +Since Cloudflare treats all other branches as preview deployments, you can easily deploy a preview of your site by triggering the workflow on any branch (e.g., `preview`). -- `CLOUDFLARE_API_TOKEN` — Create an API token in Cloudflare with "Cloudflare Pages: Edit" permissions -- `CLOUDFLARE_ACCOUNT_ID` — Found in your Cloudflare dashboard URL or account settings +```yaml +on: + push: + branches: + - prod + - preview +``` + +Pushing to the `preview` branch deploys your site to `preview.your-project.pages.dev`. To make this convenient, add another script to your `package.json`: + +```json title="package.json" +{ + "scripts": { + "push:prod": "git push origin main:prod", + "push:preview": "git push origin main:preview" + } +} +``` ---