init
This commit is contained in:
commit
c021228161
24 changed files with 1509 additions and 0 deletions
30
sites/jekyll-source/Gemfile
Normal file
30
sites/jekyll-source/Gemfile
Normal file
|
@ -0,0 +1,30 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
# Jekyll and plugins
|
||||
gem "jekyll", "~> 4.3.2"
|
||||
|
||||
# Plugins
|
||||
group :jekyll_plugins do
|
||||
gem "jekyll-paginate"
|
||||
gem "jekyll-sitemap"
|
||||
gem "jekyll-feed"
|
||||
gem "jekyll-seo-tag"
|
||||
gem "jekyll-admin"
|
||||
end
|
||||
|
||||
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
|
||||
# and associated library.
|
||||
platforms :mingw, :x64_mingw, :mswin, :jruby do
|
||||
gem "tzinfo", ">= 1", "< 3"
|
||||
gem "tzinfo-data"
|
||||
end
|
||||
|
||||
# Performance-booster for watching directories on Windows
|
||||
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
|
||||
|
||||
# Lock gem to on JRuby builds since newer versions of the gem
|
||||
# do not have a Java counterpart.
|
||||
gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
|
||||
|
||||
# When running Jekyll locally
|
||||
gem "webrick", "~> 1.8"
|
126
sites/jekyll-source/Gemfile.lock
Normal file
126
sites/jekyll-source/Gemfile.lock
Normal file
|
@ -0,0 +1,126 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
base64 (0.3.0)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.3.5)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0)
|
||||
eventmachine (1.2.7)
|
||||
ffi (1.17.2-aarch64-linux-gnu)
|
||||
ffi (1.17.2-arm64-darwin)
|
||||
ffi (1.17.2-x86_64-darwin)
|
||||
ffi (1.17.2-x86_64-linux-gnu)
|
||||
forwardable-extended (2.6.0)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (4.3.4)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
em-websocket (~> 0.5)
|
||||
i18n (~> 1.0)
|
||||
jekyll-sass-converter (>= 2.0, < 4.0)
|
||||
jekyll-watch (~> 2.0)
|
||||
kramdown (~> 2.3, >= 2.3.1)
|
||||
kramdown-parser-gfm (~> 1.0)
|
||||
liquid (~> 4.0)
|
||||
mercenary (>= 0.3.6, < 0.5)
|
||||
pathutil (~> 0.9)
|
||||
rouge (>= 3.0, < 5.0)
|
||||
safe_yaml (~> 1.0)
|
||||
terminal-table (>= 1.8, < 4.0)
|
||||
webrick (~> 1.7)
|
||||
jekyll-admin (0.12.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
rackup (~> 2.0)
|
||||
sinatra (~> 4.0)
|
||||
sinatra-contrib (~> 4.0)
|
||||
jekyll-feed (0.17.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-paginate (1.1.0)
|
||||
jekyll-sass-converter (2.2.0)
|
||||
sassc (> 2.0.1, < 3.0)
|
||||
jekyll-seo-tag (2.8.0)
|
||||
jekyll (>= 3.8, < 5.0)
|
||||
jekyll-sitemap (1.4.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
kramdown (2.5.1)
|
||||
rexml (>= 3.3.9)
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.4)
|
||||
listen (3.9.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
logger (1.7.0)
|
||||
mercenary (0.4.0)
|
||||
multi_json (1.15.0)
|
||||
mustermann (3.0.3)
|
||||
ruby2_keywords (~> 0.0.1)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (5.1.1)
|
||||
rack (3.1.16)
|
||||
rack-protection (4.1.1)
|
||||
base64 (>= 0.1.0)
|
||||
logger (>= 1.6.0)
|
||||
rack (>= 3.0.0, < 4)
|
||||
rack-session (2.1.1)
|
||||
base64 (>= 0.1.0)
|
||||
rack (>= 3.0.0)
|
||||
rackup (2.2.1)
|
||||
rack (>= 3)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.11.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.4.1)
|
||||
rouge (3.30.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
safe_yaml (1.0.5)
|
||||
sassc (2.4.0)
|
||||
ffi (~> 1.9)
|
||||
sinatra (4.1.1)
|
||||
logger (>= 1.6.0)
|
||||
mustermann (~> 3.0)
|
||||
rack (>= 3.0.0, < 4)
|
||||
rack-protection (= 4.1.1)
|
||||
rack-session (>= 2.0.0, < 3)
|
||||
tilt (~> 2.0)
|
||||
sinatra-contrib (4.1.1)
|
||||
multi_json (>= 0.0.2)
|
||||
mustermann (~> 3.0)
|
||||
rack-protection (= 4.1.1)
|
||||
sinatra (= 4.1.1)
|
||||
tilt (~> 2.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
tilt (2.6.0)
|
||||
unicode-display_width (2.6.0)
|
||||
webrick (1.9.1)
|
||||
|
||||
PLATFORMS
|
||||
aarch64-linux
|
||||
universal-darwin-24
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
http_parser.rb (~> 0.6.0)
|
||||
jekyll (~> 4.3.2)
|
||||
jekyll-admin
|
||||
jekyll-feed
|
||||
jekyll-paginate
|
||||
jekyll-seo-tag
|
||||
jekyll-sitemap
|
||||
tzinfo (>= 1, < 3)
|
||||
tzinfo-data
|
||||
wdm (~> 0.1.1)
|
||||
webrick (~> 1.8)
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.25
|
76
sites/jekyll-source/_config.yml
Normal file
76
sites/jekyll-source/_config.yml
Normal file
|
@ -0,0 +1,76 @@
|
|||
# Jekyll configuration with less-style-please theme
|
||||
title: Motherfucking Blog
|
||||
tagline: Sick of All the Shit
|
||||
description: >-
|
||||
Turning a joke into a self-hosted starter kit for motherfucking blogs.
|
||||
url: ''
|
||||
baseurl: ''
|
||||
lang: en-US
|
||||
timezone: UTC
|
||||
|
||||
# Author information
|
||||
author:
|
||||
name: Stewart Pidasso
|
||||
email: stu[at][this-site].com
|
||||
links:
|
||||
- https://github.com/Steward-Pidasso
|
||||
- https://twitter.com/username
|
||||
|
||||
# GitHub repository
|
||||
repository: username/repo-name
|
||||
|
||||
# Jekyll settings
|
||||
markdown: kramdown
|
||||
highlighter: rouge
|
||||
permalink: /:year/:month/:day/:title/
|
||||
paginate: 10
|
||||
|
||||
# Plugins
|
||||
plugins:
|
||||
- jekyll-paginate
|
||||
- jekyll-sitemap
|
||||
- jekyll-feed
|
||||
- jekyll-seo-tag
|
||||
|
||||
# Exclude files/folders
|
||||
exclude:
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- node_modules
|
||||
- vendor
|
||||
- _site
|
||||
- .sass-cache
|
||||
- .jekyll-cache
|
||||
- gemfiles
|
||||
- vendor/bundle/
|
||||
- vendor/cache/
|
||||
- vendor/gems/
|
||||
- vendor/ruby/
|
||||
|
||||
jekyll_admin:
|
||||
#You will likely need to change this depending on your template.
|
||||
metadata:
|
||||
_posts:
|
||||
- name: "layout"
|
||||
field:
|
||||
element: "hidden" # Change from "text" to "hidden"
|
||||
value: "post"
|
||||
- name: "title"
|
||||
field:
|
||||
element: "text"
|
||||
label: "Post title"
|
||||
- name: "date" # Add this field
|
||||
field:
|
||||
element: "text"
|
||||
label: "Date"
|
||||
value: "CURRENT_DATETIME" # This will use the current date/time
|
||||
- name: "categories"
|
||||
field:
|
||||
element: "text"
|
||||
label: "Categories (comma-separated)"
|
||||
placeholder: "category1, category2"
|
||||
- name: "tags"
|
||||
field:
|
||||
element: "text"
|
||||
label: "Tags (comma-separated)"
|
||||
placeholder: "tag1, tag2"
|
3
sites/jekyll-source/_config_admin.yml
Normal file
3
sites/jekyll-source/_config_admin.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Jekyll Admin specific configuration
|
||||
url: 'http://admin.localhost:333'
|
||||
baseurl: ''
|
9
sites/jekyll-source/_config_dev.yml
Normal file
9
sites/jekyll-source/_config_dev.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Development environment configuration
|
||||
url: 'http://dev.localhost'
|
||||
baseurl: ''
|
||||
environment: development
|
||||
destination: dev-site
|
||||
# Additional development-specific settings
|
||||
safe: false
|
||||
future: true
|
||||
unpublished: true
|
14
sites/jekyll-source/_config_prod.yml
Normal file
14
sites/jekyll-source/_config_prod.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Production environment configuration
|
||||
url: 'http://localhost'
|
||||
baseurl: 'https://motherfuckingblog.com'
|
||||
environment: production
|
||||
|
||||
# Additional production-specific settings
|
||||
safe: true
|
||||
future: false
|
||||
unpublished: false
|
||||
destination: prod-site
|
||||
|
||||
|
||||
# Analytics and SEO settings for production
|
||||
google_analytics: # Don't Add your Google Analytics ID here. They are a bad company.
|
1
sites/jekyll-source/_includes/analytics/umami.html
Normal file
1
sites/jekyll-source/_includes/analytics/umami.html
Normal file
|
@ -0,0 +1 @@
|
|||
<script defer src="https://fuckbigbro.motherfuckingblog.com/script.js" data-website-id="7a8d87bd-5232-42fb-8aad-5f05283b7115"></script>
|
27
sites/jekyll-source/_layouts/default.html
Normal file
27
sites/jekyll-source/_layouts/default.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ site.lang | default: "en-US" }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% if page.title %}{{ page.title | escape }} - {{ site.title | escape }}{% else %}{{ site.title | escape }}{% endif %}</title>
|
||||
<meta name="description" content="{{ page.description | default: site.description | strip_html | normalize_whitespace | truncate: 160 | escape }}">
|
||||
<link rel="stylesheet" href="{{ "/assets/css/style.css" | relative_url }}">
|
||||
{% feed_meta %}
|
||||
{% seo %}
|
||||
{% include analytics/umami.html %}
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1><a href="{{ "/" | relative_url }}">{{ site.title | escape }}</a></h1>
|
||||
<p>{{ site.tagline | escape }}</p>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
{{ content }}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>© {{ site.time | date: '%Y' }} {{ site.author.name | default: site.title }}</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
24
sites/jekyll-source/_layouts/home.html
Normal file
24
sites/jekyll-source/_layouts/home.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
<div class="home">
|
||||
{{ content }}
|
||||
|
||||
<h2>Recent Posts</h2>
|
||||
|
||||
<ul class="post-list">
|
||||
{% for post in site.posts limit:10 %}
|
||||
<li>
|
||||
<h3>
|
||||
<a class="post-link" href="{{ post.url | relative_url }}">{{ post.title | escape }}</a>
|
||||
</h3>
|
||||
<p class="post-meta">{{ post.date | date: "%b %-d, %Y" }}</p>
|
||||
{% if post.description %}
|
||||
<p>{{ post.description }}</p>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<p><a href="{{ "/archive" | relative_url }}">View all posts</a></p>
|
||||
</div>
|
46
sites/jekyll-source/_layouts/post.html
Normal file
46
sites/jekyll-source/_layouts/post.html
Normal file
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
<article class="post">
|
||||
<header class="post-header">
|
||||
<h1 class="post-title">{{ page.title | escape }}</h1>
|
||||
<p class="post-meta">
|
||||
<time datetime="{{ page.date | date_to_xmlschema }}">{{ page.date | date: "%b %-d, %Y" }}</time>
|
||||
{% if page.author %}
|
||||
• <span>{{ page.author }}</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="post-content">
|
||||
{{ content }}
|
||||
</div>
|
||||
|
||||
{% if page.tags.size > 0 %}
|
||||
<div class="post-tags">
|
||||
<p>Tags:
|
||||
{% for tag in page.tags %}
|
||||
<a href="{{ site.baseurl }}/tags/#{{ tag | slugify }}">{{ tag }}</a>{% unless forloop.last %}, {% endunless %}
|
||||
{% endfor %}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</article>
|
||||
<br>
|
||||
<h2>Recent Posts</h2>
|
||||
|
||||
<ul class="post-list">
|
||||
{% for post in site.posts limit:10 %}
|
||||
<li>
|
||||
<h3>
|
||||
<a class="post-link" href="{{ post.url | relative_url }}">{{ post.title | escape }}</a>
|
||||
</h3>
|
||||
<p class="post-meta">{{ post.date | date: "%b %-d, %Y" }}</p>
|
||||
{% if post.description %}
|
||||
<p>{{ post.description }}</p>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<p><a href="{{ "/archive" | relative_url }}">View all posts</a></p>
|
88
sites/jekyll-source/_posts/2023-05-01-welcome-to-jekyll.md
Normal file
88
sites/jekyll-source/_posts/2023-05-01-welcome-to-jekyll.md
Normal file
|
@ -0,0 +1,88 @@
|
|||
---
|
||||
title: Boilerplate Jekyll How-to
|
||||
layout: post
|
||||
date: '2025-05-01 12:00:00 +0000'
|
||||
categories:
|
||||
- jekyll
|
||||
tags:
|
||||
- getting-started
|
||||
---
|
||||
|
||||
# Welcome to Jekyll!
|
||||
|
||||
This is your first post using Jekyll with the less-style theme. Jekyll is a static site generator that transforms your plain text into static websites and blogs.
|
||||
|
||||
## How to Create Posts
|
||||
|
||||
To create a new post, simply add a file in the `_posts` directory that follows the naming convention `YYYY-MM-DD-title.md`, where `YYYY-MM-DD` is the date of your post and `title` is the title of your post.
|
||||
|
||||
At the top of each post, you need to include what's called "front matter" - this is YAML that tells Jekyll how to process the file. Here's an example:
|
||||
|
||||
```yaml
|
||||
---
|
||||
layout: post
|
||||
title: "Your Post Title"
|
||||
date: 2023-05-01 12:00:00 -0000
|
||||
categories: [category1, category2]
|
||||
tags: [tag1, tag2]
|
||||
---
|
||||
```
|
||||
|
||||
## Markdown Formatting
|
||||
|
||||
Jekyll uses Markdown for formatting. Here are some examples:
|
||||
|
||||
### Headers
|
||||
|
||||
```markdown
|
||||
# H1
|
||||
## H2
|
||||
### H3
|
||||
```
|
||||
|
||||
### Emphasis
|
||||
|
||||
```markdown
|
||||
*italic* or _italic_
|
||||
**bold** or __bold__
|
||||
```
|
||||
|
||||
### Lists
|
||||
|
||||
```markdown
|
||||
- Item 1
|
||||
- Item 2
|
||||
- Subitem 2.1
|
||||
- Subitem 2.2
|
||||
|
||||
1. First item
|
||||
2. Second item
|
||||
```
|
||||
|
||||
### Links and Images
|
||||
|
||||
```markdown
|
||||
[Link text](URL)
|
||||

|
||||
```
|
||||
|
||||
### Code
|
||||
|
||||
```markdown
|
||||
`inline code`
|
||||
|
||||
```python
|
||||
# Code block with syntax highlighting
|
||||
def hello_world():
|
||||
print("Hello, world!")
|
||||
```
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Customize your site by editing `_config.yml`
|
||||
2. Create new posts in the `_posts` directory
|
||||
3. Add pages by creating new markdown files in the root directory
|
||||
4. Customize the theme by overriding CSS in `assets/css/style.scss`
|
||||
|
||||
Happy blogging with Jekyll!
|
83
sites/jekyll-source/_posts/2025-06-22-wtf-is-this.md
Normal file
83
sites/jekyll-source/_posts/2025-06-22-wtf-is-this.md
Normal file
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
title: WTF Is this? Gimme the deets.
|
||||
layout: post
|
||||
date: '2025-07-06 15:11:26'
|
||||
---
|
||||
|
||||
[TL;DR Github Repo](http://git.motherfuckingblog.com)
|
||||
|
||||
For **99% of users**:
|
||||
- a <20kb blog about web infrastructure that they don't understand
|
||||
- they found high due to its 99% SEO Scores
|
||||
- seems different, but they don't quite know why?
|
||||
- "yeah its whatever. no ads was nice." - Average Chad
|
||||
|
||||
For **OG [MotherfuckingWebsite.com](https://motherfuckingwebsite.com)** enjoyers:
|
||||
- A way to learn about static site generators like **Jekyll** (Check out Hugo or 11ty too if this concept is new to you)
|
||||
-- A way to systemize and organize if you plan on having more than a handful of posts.
|
||||
-- Extensible, but not in the gross Wordpress way. For example, add search, table of contents, and more.
|
||||
- Some cool other shit in docker compose that makes it easier to own your data and your infrastructure.
|
||||
|
||||
|
||||
For **fucks sake whats all this other shit**:
|
||||
|
||||
- Isn't it weird products don't ship with **security** natively included? It's opinionated, but its safer than default in the othr shit.
|
||||
- *Traefik* - Reverse proxy your management interfaces and IP Allowlist them in an easy way. Secure yourself against any dumb idea you are bound to add later.
|
||||
- *Crowdsec WAF* - Crowdsec is legit innovating and deserves more attention. Crowdsourced blacklisting and malicious signature detection.
|
||||
- Data Privacy:
|
||||
- *Forgejo* - FOSS Github. Better Post Revision History than Wordpress. But
|
||||
- *Umami* - FOSS Google Analytics Alternative. Privacy forward, 1st party.
|
||||
|
||||
|
||||
## How TF Do I Make A Blog
|
||||
Configure your DNS and Firewall on your cloud provider. You should restrict port `333` to trust IP addresses only.
|
||||
|
||||
In the example I have used Linode API to get a wildcard cert. If you don't care about TLS, you are wrong, but I get it. Traefik will create self signed certs for you, but you will likely need to remove or modify the TLS settings in the compose file.
|
||||
|
||||
Once you have set up your cloud provider:
|
||||
|
||||
```
|
||||
git clone thisRepo
|
||||
cd thisRepo
|
||||
cp .env.example .env
|
||||
vim .env # make it match your environment
|
||||
docker compose up
|
||||
```
|
||||
### Deployment
|
||||
It is capable of running on a 1 shared CPU, with 2GB of RAM as tested on Linode.
|
||||
|
||||
Running on 2 shared CPUs with 4 GB of ram is sufficient for the full stack to run as smooth as butter for 99% of all users. On my personal fork unrelated to motherfuckingblog.com, I keep my Forgejo instance on another server with a Nextcloud instance and additional hardening. This isn't a bible, its a starter kit to make it easier for normal people to iterate from. Take what you need and throw the rest out.
|
||||
|
||||
|
||||
|
||||
### Security
|
||||
Products should ship secure by default or at the least have a small handful of options that are easy to configure and harden.
|
||||
|
||||
This comes with Crowdsec WAF which will share limited data with crowdsec. If strict data isolation is essential. You need to remove this and consider a different WAF. There are alternatives, but at least be aware of what you are losing. Crowdsec with AppSec protects against human laziness. Essentially it acts as a real-time updated block list that matches against known malicious signatures in outdated software that you probably haven't patched yet, ya filthy animal.
|
||||
|
||||
All Admin Interfaces are restricted to an IP Allowlist. Almost every Org has VPNs, this is what they are meant for.
|
||||
**If you are a noob** and you just `curl icanhazip.com ` then paste in your IP. *Prepare to temporarily lose access*. Your ISP will rotate your IP and you will think you are SOL. You are not. You need your own private VPN (which is actually easy to do), or you need to bind these to the local interface then perform ssh port forwarding anytime you want to perform maintenance. That sounds scary, but I promise it is like two simple commands. I'm pretty sure you can just change the port binding at the top of the compose file from `333:333` to `127.0.0.1:333:333`. Then you simply `ssh user@remote -L 333:127.0.0.1:333`
|
||||
|
||||
The Jekyll Admin interface had no authentication by default so basic http authentication was added via Traefik.
|
||||
|
||||
Additionally there is a strong benefit to using a non-standard port / custom entry point in Traefik (port 333 in this example) in the docker-compose file for this project. This allows for redudant whitelisting. On my cloud provider I also whitelist my IP address to those ports and deny all others. This means even if traefik IPAllowlisting is bypassed via some hacker black magic, I have a secondary defense.
|
||||
|
||||
|
||||
|
||||
#### Random Aside
|
||||
|
||||
It's just insane to me we just leave admin login portals open in the wild. WTF are we doing?
|
||||
|
||||
> Please guess employee passwords on my public website an unlimited number of times.
|
||||
> \- **Every Chief Information Security Officer**
|
||||
|
||||
|
||||
### Issues
|
||||
|
||||
##### It's ugly!
|
||||
While, I find this beautiful. You may perfer one of the thousands of free themes for Jekyll which will make your site look exactly like the corporate garbage flooding the internet.
|
||||
|
||||
##### X Feature is Broken
|
||||
Yep! Personally I know of the error that appears, but is incorrect in jekyll admin interface. But honestly that is at least half the point. If you properly restrict your broken tech behind network level access controls it mitigates the risk for a large portion of people.
|
||||
|
||||
Also this isn't a pick it up and make an identical blog. It is a starter kit. I know half of you are going to rip Jekyll admin out. If you plan on using it you are welcome to open issues with them or figure out the way to use. It works for my purposes and allows me to create, edit, and tag posts. I need nothing else.
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
title: Obligatory Rant/Background
|
||||
layout: post
|
||||
---
|
||||
|
||||
All I wanted was a simple small af static blog where I owned the stack and the data. But the **problems**:
|
||||
* Thinking about CSS between paragraphs ruins my ability to write.
|
||||
* TinyMCE's minified and compressed core is [100x larger](https://github.com/tinymce/tinymce/issues/4028) than my entire front end codebase.
|
||||
* Managing more than a dozen posts is a nightmare.
|
||||
* Wordpress is somehow even worse.
|
||||
* Need to add search, tags, or any other features? Almost everything requires Node, PHP, or something insane that is probably millions of times larger than my entire codebase.
|
||||
* Hosting? Every Jekyll post is how to host on Microsoft's Github. (Surely Microsoft would [never](https://arstechnica.com/information-technology/2025/02/copilot-exposes-private-github-pages-some-removed-by-microsoft/) [misuse](https://www.wired.com/story/github-commercial-ai-tool-built-open-source-code/) your data. )
|
||||
* Want to know if anyone even looked at your site? Good thing Google hasn't been using your data to literally facilitate a genocide or anything... [oh wait](https://web.archive.org/web/20240720084622/https://www.wired.com/story/amazon-google-project-nimbus-israel-idf/).
|
||||
|
||||
|
||||
So this is my opinionated attempt to move the needle the other direction.
|
||||
|
||||
**If you didn't understand anything I just said** throw it in an LLM/"AI" and ask it to explain. You can understanding anything you set your mind to. Don't doubt yourself.
|
||||
|
||||
**For the Nerds who are still with me**: This is a ***self-hosted*** **starter kit** for people sick of big bro. It is at the point where it could be taken several directions.
|
||||
- Dev and Prod versions of the site for development? Check.
|
||||
- 10kb static site? Check
|
||||
- Layers of security? Check
|
||||
- First Party data? Check
|
||||
|
||||
Check out other posts for some ideas or to learn more. In short, this is an opinionated **Docker Compose** project that uses:
|
||||
- **Traefik** for reverse proxying all admin interfaces.
|
||||
- **Jekyll** the same tech behind Github Pages, to build static sites.
|
||||
- **Nginx** as the lightweight webserver.
|
||||
- **Forgejo** for version control.
|
||||
- **Umami Analytics** we are all a little vain.
|
||||
- **Crowdsec WAF** for additional security.
|
||||
|
||||
This gives me a clean, cloud-based markdown writing environment with proper version control and monitoring.
|
||||
|
||||
|
||||
### Deployment
|
||||
It is capable of running on a 1 shared CPU, with 2GB of RAM. RAM is the limiting factor.
|
||||
Running on 2 shared CPUs with 4 GB of ram is sufficient for the full stack to run as smooth as butter for 99.9% of all users.
|
||||
|
||||
On my personal fork unrelated to motherfuckingblog.com, I keep my Forgejo instance on another server with a Nextcloud instance and additional hardening. This isn't a bible, its a starter kit to make it easier for normal people to iterate from. Take what you need and throw the rest out.
|
||||
|
||||
|
||||
|
||||
### Security
|
||||
Products should ship secure by default or at least have a small handful of options that are easy to configure and harden the product.
|
||||
|
||||
This comes with Crowdsec WAF which will share limited data with crowdsec. If strict data isolation is essential. You need to remove this and consider a different WAF. There are alternatives, but at least be aware of what you are losing. Crowdsec with AppSec protects against human laziness. Essentially **it acts as a real-time updated block list** that matches against known malicious signatures in outdated software that you probably haven't patched yet, ya filthy animal.
|
||||
|
||||
***All Admin Interfaces are restricted to an IP Allowlist.*** Almost every Org has VPNs, this is what they are meant for.
|
||||
*If you are a complete noob*. It is okay. You will need to learn a bit to use this project, but it is within grasp. Don't discount yourself. **There is a big gotcha here.** If you just `curl icanhazip.com ` then paste in your IP on the allowlist. It will work. YAY! Party time! But *prepare to temporarily lose access*. Your ISP will rotate your IP and you will think you are shit outta luck. You are not. Ideally you would use your own private VPN (which they literally have scripts to deploy, it's easy to do), or you need to bind these to the local interface then perform ssh port forwarding anytime you want to perform maintenance/ view your dashboards. That sounds scary, but I promise it is like two simple commands. Though some additional config is probable.
|
||||
|
||||
The **Jekyll Admin interface had no authentication by default so basic http authentication was added** via Traefik. For God's sake, keep your admin interfaces from being externally accessible to anyone but trusted individuals.
|
||||
|
||||
|
||||
Lastly, there is a strong benefit to **using a non-standard port / custom entry point in Traefik** (port 333 in this example) in the docker-compose file for this project. This allows for redudant whitelisting. On my cloud provider I also whitelist my IP address to those ports and deny all others. This means even if Traefik `IPAllowlist` is bypassed via some hacker black magic, I have a secondary defense.
|
32
sites/jekyll-source/archive.md
Normal file
32
sites/jekyll-source/archive.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
layout: default
|
||||
title: Archive
|
||||
---
|
||||
|
||||
# Archive
|
||||
{::nomarkdown}
|
||||
{% assign current_year = "" %}
|
||||
{% for post in site.posts %}
|
||||
{% assign post_year = post.date | date: "%Y" %}
|
||||
|
||||
{% if post_year != current_year %}
|
||||
{% unless forloop.first %}
|
||||
</ul>
|
||||
{% endunless %}
|
||||
|
||||
<h2 id="y{{ post_year }}">{{ post_year }}</h2>
|
||||
<ul class="post-list">
|
||||
|
||||
{% assign current_year = post_year %}
|
||||
{% endif %}
|
||||
|
||||
<li>
|
||||
<span class="post-meta">{{ post.date | date: "%b %-d" }}</span>
|
||||
<a href="{{ post.url | relative_url }}">{{ post.title }}</a>
|
||||
</li>
|
||||
|
||||
{% if forloop.last %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{:/}
|
102
sites/jekyll-source/assets/css/style.scss
Normal file
102
sites/jekyll-source/assets/css/style.scss
Normal file
|
@ -0,0 +1,102 @@
|
|||
---
|
||||
---
|
||||
|
||||
// less-style-please theme styling
|
||||
// Inspired by https://feeshy.github.io/less-style-please/
|
||||
|
||||
html {
|
||||
font-size: 100%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
body {
|
||||
max-width: 650px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem 1rem;
|
||||
}
|
||||
|
||||
header, footer {
|
||||
text-align: center;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0366d6;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
|
||||
font-size: 0.9em;
|
||||
background-color: #f6f8fa;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 1rem;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 0.2em 0.4em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin-left: 0;
|
||||
padding-left: 1rem;
|
||||
border-left: 4px solid #ddd;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 0.5rem;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f6f8fa;
|
||||
}
|
||||
|
||||
.post-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.post-list li {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.post-meta {
|
||||
color: #666;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 2rem 0;
|
||||
}
|
26
sites/jekyll-source/index.md
Normal file
26
sites/jekyll-source/index.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
title: Motherfucking Blog
|
||||
layout: home
|
||||
---
|
||||
|
||||
## What if it wasn't satire?
|
||||
The OG motherfuckingwebsite.com (and the spinoffs) all insisted it was satire, but what if it wasn't? Seriously, look at all this unvarnished negative space. It is beautiful. Does your brain even know what to do when it isn't being inundated with ads or upsells?
|
||||
|
||||
<div markdown="0"><br><br></div>
|
||||
|
||||
##### Just stop and dwell in the empty space.
|
||||
|
||||
<div markdown="0"><br><br><br></div>
|
||||
|
||||
|
||||
This isn't meditation. This is respect for you as a living being. You have probably never seen it on the internet.
|
||||
|
||||
You came here to see one madman's ravings and that is all you are getting. No insane nagging for a login or subscription. No selling you some shit you don't need. No cookies or their pain in the ass banners. No giving your data to other people. ***It's just you and an idea. It's fucking magical.*** I want it to happen more often so I put it in an easy to replicate package.
|
||||
|
||||
At a high-level, this is **self-hosted starter-kit of a blog platform** which makes it easier for tech and tech-curious people to create a diversity of blogs which are safer and respect end-users without any explicit dependencies on big tech. Oh and of course it is entirely free.
|
||||
|
||||
It satisfies the basic needs of four teams:
|
||||
- **Devs**: Trusted Jekyll ecosystem with statically deployed pages that can run on a very small instance. Version control through Forgejo optional, but included.
|
||||
- **Content Creators**: WYSIWYG Markdown editor with SEO optimizations.
|
||||
- **Analytics and Data**: 1st party data without cookies.
|
||||
- **Security**: Crowdsourced WAF. IP Allowlisting. TLS. Reverse Proxy. Redudant controls.
|
Loading…
Add table
Add a link
Reference in a new issue