Compare commits
19 Commits
8aa1807e25
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 4873fd9981 | |||
| 8b2c0f301e | |||
| ff671f3c35 | |||
| bcc9753a81 | |||
| ca66e70b4a | |||
| fea2ed5d51 | |||
| b96391d813 | |||
| 5feb3e334b | |||
| d74e93c704 | |||
| 1fe91ded10 | |||
| 29315403fd | |||
| 3545f76842 | |||
| 13fdadd1bf | |||
| 0fde7cafba | |||
| c70fcef832 | |||
|
|
33c4db008d | ||
|
|
a025f57afb | ||
| d83b85ca3f | |||
| a59944447f |
27
.gitea/workflows/build-and-deploy.yaml
Normal file
27
.gitea/workflows/build-and-deploy.yaml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: Build and Deploy Blog Site
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
setup-website-content:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: shockrah/hugo
|
||||||
|
steps:
|
||||||
|
- run: git init
|
||||||
|
- run: git remote add origin https://git.shockrah.xyz/shockrah/blog.git
|
||||||
|
- run: git pull origin master
|
||||||
|
- name: Build website content
|
||||||
|
run: hugo
|
||||||
|
- name: Copy files with rsync
|
||||||
|
uses: tempersama/rsync-copy@2.6
|
||||||
|
with:
|
||||||
|
host: shockrah.xyz
|
||||||
|
username: ${{ secrets.USER }}
|
||||||
|
source: "public/"
|
||||||
|
destination: /opt/nginx/shockrah.xyz/
|
||||||
|
key: ${{ secrets.PRIVATE_KEY }}
|
||||||
|
|
||||||
|
|
||||||
8
archetypes/default.md
Normal file
8
archetypes/default.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
title: {{ replace .File.ContentBaseName "-" " " | title }}
|
||||||
|
description: null
|
||||||
|
date: {{ .Date }}
|
||||||
|
draft: false
|
||||||
|
category: article
|
||||||
|
---
|
||||||
|
|
||||||
@@ -5,5 +5,7 @@ description = "Place to post stuff"
|
|||||||
|
|
||||||
theme = "shockrah.xyz"
|
theme = "shockrah.xyz"
|
||||||
|
|
||||||
|
enableEmoji = true
|
||||||
|
|
||||||
[markup.goldmark.renderer]
|
[markup.goldmark.renderer]
|
||||||
unsafe = true
|
unsafe = true
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ description = "Place to post stuff"
|
|||||||
|
|
||||||
theme = "shockrah.xyz"
|
theme = "shockrah.xyz"
|
||||||
|
|
||||||
|
enableEmoji = true
|
||||||
|
|
||||||
[markup.goldmark.renderer]
|
[markup.goldmark.renderer]
|
||||||
unsafe = true
|
unsafe = true
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ description = "Place to post stuff"
|
|||||||
|
|
||||||
theme = "shockrah.xyz"
|
theme = "shockrah.xyz"
|
||||||
|
|
||||||
|
enableEmoji = true
|
||||||
|
|
||||||
[markup.goldmark.renderer]
|
[markup.goldmark.renderer]
|
||||||
unsafe = true
|
unsafe = true
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "How this site came to be"
|
title: "How this site came to be"
|
||||||
date: July 22, 2018
|
date: 2018-06-22
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "Delivering whole OS's in Gitlab's CI/CD"
|
title: "Delivering whole OS's in Gitlab's CI/CD"
|
||||||
date: 0000-00-00
|
date: 2021-08-15
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "Drive Recover"
|
title: "Drive Recover"
|
||||||
date: 0000-00-00
|
date: 2021-08-14
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Economical Eats
|
title: Economical Eats
|
||||||
date: 0000-00-00
|
date: 2021-08-14
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Esports Post
|
title: Esports Post
|
||||||
date: 0000-00-00
|
date: 2021-08-14
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "DWM and POP!\_OS"
|
title: "DWM and POP!\_OS"
|
||||||
date: 0000-00-00
|
date: 2021-08-14
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
BIN
content/media/thumbnails/slimevr.png
LFS
Normal file
BIN
content/media/thumbnails/slimevr.png
LFS
Normal file
Binary file not shown.
@@ -24,5 +24,4 @@ It's _very_ stream of concious-y and often not super coherent so often there gap
|
|||||||
|
|
||||||
## Design things
|
## Design things
|
||||||
|
|
||||||
* Nothing Yet
|
* :wave: [Bubble Chat and it's User Data](/notes/rationalizing-user-data)
|
||||||
|
|
||||||
|
|||||||
43
content/notes/rationalizing-user-data.md
Normal file
43
content/notes/rationalizing-user-data.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
title: Rationalizing User Data
|
||||||
|
description: "Like how do I approach storing sensitive user data in Bubble?"
|
||||||
|
date: 2025-01-07T21:34:12-08:00
|
||||||
|
draft: false
|
||||||
|
category: article
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
This is a stream of concious post where I go through the process of figuring out
|
||||||
|
how I am going to store user data in my [bubble project](https://git.shockrah.xyz/shockrah/bubble)
|
||||||
|
|
||||||
|
Schema for the users can be found here: [link](https://git.shockrah.xyz/shockrah/bubble/src/branch/main/db/setup-tables.sql)
|
||||||
|
|
||||||
|
|
||||||
|
# Pre-requisites
|
||||||
|
|
||||||
|
* Using Postgres
|
||||||
|
* Hashed and salted passwords
|
||||||
|
|
||||||
|
# User ID's
|
||||||
|
|
||||||
|
By default I was going to use regular ID's that increment on each insertion.
|
||||||
|
Considering using some form of UUID's for the sake of a slight increase in sec.
|
||||||
|
Even though this isn't a major form of security, every layer towards
|
||||||
|
better security counts, and I see this as one more layer to add.
|
||||||
|
|
||||||
|
|
||||||
|
UUID's tend to suffer from indexing issues but later versions of UUID seem to
|
||||||
|
have this figured out.
|
||||||
|
|
||||||
|
After some reading v7 seems like the move.
|
||||||
|
|
||||||
|
* Time based meaning sorting ( and thus searching ) is reasonably performant
|
||||||
|
* Sufficient entropy for this case ( 74 bits ). We want ****some* entropy but also
|
||||||
|
don't want to nuke performance
|
||||||
|
* While we want to make it harder to guess, aiming for "unguessable" is just not
|
||||||
|
reasonable. UUIDv4 is best for that but compromises performance so hard it's not
|
||||||
|
worth it in the grand scheme of things
|
||||||
|
|
||||||
|
|
||||||
|
IDK v7 feels like a good middle ground for security + performance for the **user id**
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Building a Video Streaming Service with Rust
|
title: Building a Video Streaming Service with Rust
|
||||||
date: 2021-13-10
|
date: 2021-10-13
|
||||||
draft: true
|
draft: true
|
||||||
description: The real state of Rocket right now
|
description: The real state of Rocket right now
|
||||||
category: article
|
category: article
|
||||||
|
|||||||
91
content/posts/diy-slimevr.md
Normal file
91
content/posts/diy-slimevr.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
---
|
||||||
|
title: Building SlimeVR Trackers for Full Body Tracking
|
||||||
|
date: 2023-03-29
|
||||||
|
draft: false
|
||||||
|
description: From the cost, parts, and expectations. A full tutorial
|
||||||
|
category: article
|
||||||
|
image: /media/thumbnails/slimevr.png
|
||||||
|
---
|
||||||
|
|
||||||
|
# Goal
|
||||||
|
|
||||||
|
To build a Full body set of trackers:
|
||||||
|
|
||||||
|
* 7 trackers
|
||||||
|
* 3 extensions
|
||||||
|
|
||||||
|
|
||||||
|
# Parts List & Prices
|
||||||
|
|
||||||
|
**NOTE:** *Some extra components were purchased in case of defects*
|
||||||
|
|
||||||
|
:warning: Huge caveats about the purchase list below :warning:
|
||||||
|
|
||||||
|
1. Buy more parts than I did, ( especially BMI's ) because
|
||||||
|
some of these have a horrible failure rate. 15+
|
||||||
|
|
||||||
|
2. Maybe throw in an extra D1 ( 11 total ) because these can fail too.
|
||||||
|
|
||||||
|
3. Batter chargers tend to be fine but can be prone to getting burned so be careful when soldering.
|
||||||
|
|
||||||
|
## Main parts from AliExpress:
|
||||||
|
|
||||||
|
* `10` D1 Mini for `20.53$`
|
||||||
|
* `13` BMI 160 for `18.99$`
|
||||||
|
* `10` 18650 Battery **chargers** for `6.81$`
|
||||||
|
* Keep in mind that this will also work for regular LIPO batteries
|
||||||
|
* *See battery section for explanation*
|
||||||
|
|
||||||
|
## Small parts from AliExpress:
|
||||||
|
|
||||||
|
* 10 pack of DPDT 2P2T Panel Mount Switches for `2.99$`
|
||||||
|
* 100 pack of 30K ohms for `4.05$`
|
||||||
|
* 5 pack of 4Pin JST connections for `4.93$`
|
||||||
|
* 50 pack of diodes for `2.53$`
|
||||||
|
|
||||||
|
## Batteries
|
||||||
|
|
||||||
|
For reference I bought:
|
||||||
|
|
||||||
|
* `1` ( 10 piece ) EHAO 804040 3.7V 18mAh for `32.77$`
|
||||||
|
|
||||||
|
While these do work, shipping time is pretty awful compared to everything else.
|
||||||
|
Looking at the order of a few months for some vendors.
|
||||||
|
To deal with this problem we can swap those out for some `18650`'s:
|
||||||
|
|
||||||
|
* 10 pack of battery clips `7.99$`
|
||||||
|
* Set of 10 batteries for `33.32$`
|
||||||
|
|
||||||
|
* Total with taxes: `41.14$`
|
||||||
|
|
||||||
|
I can attest that `18650batteries.com` is a reputable place to get batteries.
|
||||||
|
*SideNote: includes shipping but you're mileage may vary depending on source*
|
||||||
|
|
||||||
|
## Total Initial Cost With Shipping and Taxes
|
||||||
|
|
||||||
|
If you buy the 804040 batteries: `93.60$`
|
||||||
|
|
||||||
|
With the 18650's: `101.97$`
|
||||||
|
|
||||||
|
## Assembly
|
||||||
|
|
||||||
|
### Assumptions
|
||||||
|
|
||||||
|
That the parts list above is being used however the points below
|
||||||
|
are kept somewhat general.
|
||||||
|
|
||||||
|
### Equipment
|
||||||
|
|
||||||
|
Important to note that if you don't have soldering equipment you'll need
|
||||||
|
to get some.
|
||||||
|
Cheap kits can be found for under 50$ but make sure you have plenty of solder.
|
||||||
|
|
||||||
|
1. 18650's are heavy so if possible
|
||||||
|
|
||||||
|
For this reason it's not a bad idea to get some battery clips and mount
|
||||||
|
everything to that to keep things compact. When the weight of a tracker
|
||||||
|
is imbalanced then it's much harder to mount as it tends to "swing" more.
|
||||||
|
|
||||||
|
2. Heat shrink of varying sizes to clean up splices is basically required.
|
||||||
|
|
||||||
|
3. \*Flux if you want however this is really not required at all.
|
||||||
77
content/posts/making-soap.md
Normal file
77
content/posts/making-soap.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
title: DIY Detergent
|
||||||
|
date: 2023-07-05
|
||||||
|
draft: false
|
||||||
|
description: Cheap detergent at home
|
||||||
|
category: article
|
||||||
|
image:
|
||||||
|
---
|
||||||
|
|
||||||
|
# Making detergent at home.
|
||||||
|
|
||||||
|
Recipe and instructions are followed by some interesting things I found
|
||||||
|
regarding cost and availability.
|
||||||
|
|
||||||
|
# Recipe
|
||||||
|
|
||||||
|
* 1 Part Borax
|
||||||
|
* 1 Part Baking Soda ( Sodium *Bi-Carbonate* )
|
||||||
|
* 1 Washing soda Semi-Optional ( Sodium *Carbonate* )
|
||||||
|
* **NOTE**: Can be made from baking soda if you can't find it in stores
|
||||||
|
* **NOTE**: While not required does greatly improve the quality of the detergent
|
||||||
|
|
||||||
|
Optional additions
|
||||||
|
* 1 Bar of Soap ( optional )
|
||||||
|
* No liquid soap will not work for this
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Mix Borax, Baking Soda, and Washing Soda evenly in a container. If you are using
|
||||||
|
a bar of soap you can use a cheese grater to break it down so that you can mix
|
||||||
|
this in with the rest.
|
||||||
|
|
||||||
|
## Making Washing Soda ( Sodium *Carbonate* )
|
||||||
|
|
||||||
|
Since this stuff can be hard to find you can also make it at home.
|
||||||
|
|
||||||
|
Here's a video from __[NileRed](https://www.youtube.com/watch?v=cpGEc-pLXN4).__
|
||||||
|
|
||||||
|
Quick transcription:
|
||||||
|
|
||||||
|
1. Pour out baking soda ( sodium bi-carbonate ) into a pot
|
||||||
|
2. As it heats up it will release CO2 and water
|
||||||
|
* This results in some bubbling
|
||||||
|
3. Keep heating until bubbling stops and the powder appears like a dense powder.
|
||||||
|
|
||||||
|
|
||||||
|
# FAQ & Stuff about cost
|
||||||
|
|
||||||
|
> Is this actually cheaper than just buying a regular detergent?
|
||||||
|
|
||||||
|
From my _very_ quick checks of prices around me I found Target had 16oz boxes of baking soda for 1$. A 4 lb box of Borax was 8$.
|
||||||
|
|
||||||
|
For 3 pounds of detergent you would be looking at a 10$ investment of materials.
|
||||||
|
|
||||||
|
* 1 lb baking soda ( 1$ )
|
||||||
|
* 1 lb baking soda converted to washing soda ( 1$ )
|
||||||
|
* 1 lb borax ( 2$ )
|
||||||
|
|
||||||
|
In total **4$** for 3 pounds of unscented detergent isn't too bad.
|
||||||
|
|
||||||
|
> Are there any alternatives to this sort of thing?
|
||||||
|
|
||||||
|
Dish soap unironically works well enough for small loads you just have
|
||||||
|
to play with the quantities.
|
||||||
|
|
||||||
|
> What about unit prices for all of these things?
|
||||||
|
|
||||||
|
Borax: https://www.intratec.us/chemical-markets/borax-price
|
||||||
|
|
||||||
|
Baking Soda: https://www.intratec.us/chemical-markets/sodium-bicarbonate-price
|
||||||
|
|
||||||
|
_Not including soap because this depends highly on what soap you choose_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
64
content/posts/migrating-to-vultr.md
Normal file
64
content/posts/migrating-to-vultr.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
title: Migrating to Vulr
|
||||||
|
description: Finally moving away from AWS little by little
|
||||||
|
date: 2024-10-27T20:59:05-07:00
|
||||||
|
draft: false
|
||||||
|
category: article
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
# What and Why
|
||||||
|
|
||||||
|
|
||||||
|
For some time now I've been trying my best to get away from using AWS
|
||||||
|
for my infrastructure due to the constantly rising price of everything.
|
||||||
|
|
||||||
|
|
||||||
|
## Main causes for higher cost
|
||||||
|
|
||||||
|
* Fargate
|
||||||
|
|
||||||
|
This one is mostly my own fault lmao since Fargate ( without an application load
|
||||||
|
balancer ) is actually not that bad in terms of pricing. The issue comes in
|
||||||
|
if you are trying to host a variety of services like myself on one host.
|
||||||
|
Services which, are only ever really used for personal and singular use.
|
||||||
|
|
||||||
|
Recall that with fargate we are paying for things on a core count and if you
|
||||||
|
containize everything this effectively means you are paying per container
|
||||||
|
more/less. Couple this with lots of contains and your pricing starts to
|
||||||
|
get really expensive really fast.
|
||||||
|
|
||||||
|
* Application Load Balancer
|
||||||
|
|
||||||
|
These are just expensive for small projects what else can I say...
|
||||||
|
I wouldn't suggest hosting personal sites behind one of these basically ever.
|
||||||
|
|
||||||
|
* Scaling
|
||||||
|
|
||||||
|
If you seriously need an ALB to sit in front of lots of microservices then
|
||||||
|
you're probably dealing with either an interesting project or just a need
|
||||||
|
to handle a lot of traffic. After a while I didn't really want a web server
|
||||||
|
to be my "interesting project" since this ended up eating way more of my time
|
||||||
|
than I would have ever liked it to...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Why Vultr
|
||||||
|
|
||||||
|
shit's cheap yo...
|
||||||
|
|
||||||
|
10$ - 20$ roughly for a bare minimum Kubernetes cluster or about 10$ per
|
||||||
|
host as I'm doing now. Provision hosts with Terraform then configure with
|
||||||
|
Ansible and you have a somewhat reasonable infrastructure for hosting
|
||||||
|
personal projects.
|
||||||
|
|
||||||
|
## What Do I host now?
|
||||||
|
|
||||||
|
* shockrah.xyz
|
||||||
|
* git.shockrah.xyz <-- Gitea instance
|
||||||
|
* temper.tv <-- vr/funsies blog
|
||||||
|
|
||||||
|
Basically I'm hosting more stuff more effectively and it's an infrastructure
|
||||||
|
that is ""(([[{{platform agnostic}}]]""given its all Terraform anyway and
|
||||||
|
Ansible can be used basically anywhere there's a host.
|
||||||
|
|
||||||
87
content/posts/password-managers.md
Normal file
87
content/posts/password-managers.md
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
---
|
||||||
|
title: Password Managers
|
||||||
|
description: just use unix pass
|
||||||
|
date: 2024-04-30T16:12:04-07:00
|
||||||
|
draft: false
|
||||||
|
category: article
|
||||||
|
---
|
||||||
|
|
||||||
|
# `pass` Shilling
|
||||||
|
This one is gonna be short but I've come shill password manager that:
|
||||||
|
|
||||||
|
* Allows for simple generation of passwords
|
||||||
|
* Allows for easy backups to be made
|
||||||
|
* Is compatible with basically any password access workflow you can think of
|
||||||
|
* Is completely foss
|
||||||
|
* Allows for both single and multiline passwords
|
||||||
|
* Allows for optional opt-in versioning using git ( as a subcommand )
|
||||||
|
* Can also be used with other VCS's
|
||||||
|
|
||||||
|
It's called `pass` --> https://www.passwordstore.org/
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
Here's an example of how it works
|
||||||
|
|
||||||
|
|
||||||
|
Simple Generation of passwords:
|
||||||
|
|
||||||
|
```
|
||||||
|
~ pass generate example 100
|
||||||
|
[master 3cfe907] Add generated password for example.
|
||||||
|
1 file changed, 0 insertions(+), 0 deletions(-)
|
||||||
|
create mode 100644 example.gpg
|
||||||
|
The generated password for example is:
|
||||||
|
9m/Mk5WzLE75=QzhdD;T>}keXOv')FOh~S(=J43OAZ2qkxg<I>hjUJGRpav%oI<yq!ULw0<)@#P|+y0C2~q[O2=&^x{P_\v'K@\B
|
||||||
|
```
|
||||||
|
|
||||||
|
Want to straight up just copy it directly? Ok here you go with `-c`
|
||||||
|
|
||||||
|
```
|
||||||
|
pass generate example2 100 -c
|
||||||
|
[master 55599f0] Add generated password for example2.
|
||||||
|
1 file changed, 0 insertions(+), 0 deletions(-)
|
||||||
|
create mode 100644 example2.gpg
|
||||||
|
Copied example2 to clipboard. Will clear in 45 seconds.
|
||||||
|
```
|
||||||
|
|
||||||
|
# Why tho
|
||||||
|
|
||||||
|
Because it's completely dead simple to the point of absurdity. Want a really
|
||||||
|
weird use case; pipe the output into a `qr` command and generate completely
|
||||||
|
random qr codes. Using the same example as above:
|
||||||
|
|
||||||
|
```
|
||||||
|
pass example | qr
|
||||||
|
█████████████████████████████████████████████████
|
||||||
|
█████████████████████████████████████████████████
|
||||||
|
████ ▄▄▄▄▄ ███▄▄▄ ▀▀▀▄▀▄▀ ▄▀▀▄ ▀█▄▀▄ █ ▄▄▄▄▄ ████
|
||||||
|
████ █ █ ████ █▀▄▀ ▀ ▄█▀ ▄ █▀▀█▄ █▀█ █ █ ████
|
||||||
|
████ █▄▄▄█ █▀▄ ▀▄▀ ▀█ ▀▀▄█▄▀ ▀▀ ▄▀▀ █ █▄▄▄█ ████
|
||||||
|
████▄▄▄▄▄▄▄█▄▀▄▀ ▀ ▀ ▀ ▀ ▀▄█▄█ █▄▀▄█▄█▄▄▄▄▄▄▄████
|
||||||
|
████▄▀█ █ ▄▀ ▀▄▀▄ ▄▄▀▄▀█▀██ ▀▄█ ▀▄▀▄█▀▀█▀████
|
||||||
|
████ █▄▄ ▀▄ ▄█▀▄▄ █ █▄▄▀▀██ ▄▀ █▀▄ ▄ ▄▄█ ▀████
|
||||||
|
████▀▄▄▄█▄▄▀██ ▀█ ▄▄▄▄█▄█ ▀▀▀▀▀ ███▄▀█▄██▀█▀ ████
|
||||||
|
████▄▀ █▀▄▄ ▀▄▀ ▄ ▄▀ ▀▄▀▄ ▄▀▄█▀ ██▀█▀█▀ ▄ ████
|
||||||
|
████▀▄ ▀█▄▄ ▄▄█ ██▀ ▄ ▄ █▀▄▀█ ▀ ▄█▀▀█▄▀▀ ████
|
||||||
|
█████ ▀▀▀█▄▀▄████ ▄▄ ▀ █ ▀ ▄█▀▀▀▄▀▀▀▀▄ █▀▄████
|
||||||
|
████ ▀ ▀██▄▀ ▀▀ ▄█ ▄▀▄ ▄▄▀▄█ ▄█▀ ▀▀▄█▄ ▄▄▄▀▄ ████
|
||||||
|
█████▀▄██▀▄▄ ▄█▄█▀▀█▄█▄ ▀▀▄██▀ █▄█▀▄▀ ▀▄▀▄▀██████
|
||||||
|
████▀█ █▄ ▄ ▄ █ ▀ ███ ▄▀ ██▀▄ ▀▀▀▄██ ▀▄▄████
|
||||||
|
█████ ▄ ▀█▄█ ▄██▄▀ ▀▀▄▀ ▀ █▀▀▀▄█ ▀ ▄ ██ ████
|
||||||
|
████▄▀▄▄██▄▄▄ ▀▀▄▄▄▄█▀▀▄ ▀█ ▀▄▀ ▄ █▀▀▄ █▀█████
|
||||||
|
████▄██▀ ▄▄ ▀▄▄██ ▄▄▀▄ ▄██▄▀▀ ▀ █▀▄ ██ ▄▄ ████
|
||||||
|
████▄███▄▄▄▄ ▀▄ █▀ ██▄█▄ █▀██ ▀█▄█▀ ▄▄▄ ▀█▄ ████
|
||||||
|
████ ▄▄▄▄▄ █▀▄▄ ▄▄▄▄▄ █ ██▄▀█▀▄▄ █ █▄█ ▄▀▄▀████
|
||||||
|
████ █ █ █▀ ▀ ▀▀▀▄ ███ █ █▀▀██▀▀▀▀▄▄ ▄▄█ █████
|
||||||
|
████ █▄▄▄█ ████▄▀█▀ ▄▀▄▀▀ █▄▄▀█▀ ▀▀▄█▄ █ ▄█ ▄████
|
||||||
|
████▄▄▄▄▄▄▄█▄▄█▄█▄█▄▄▄███▄▄█▄███▄▄▄█▄█▄▄██▄▄█████
|
||||||
|
█████████████████████████████████████████████████
|
||||||
|
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||||
|
```
|
||||||
|
|
||||||
|
Also each password is just a file in a directory tree which means you can sort
|
||||||
|
things however you'd like which is also neat. Anyway that is all I had for now
|
||||||
|
just thought this program I've been using for a while now was cool and deserved
|
||||||
|
a quick post about it :smile:
|
||||||
|
|
||||||
41
content/posts/reviving-an-old-project.md
Normal file
41
content/posts/reviving-an-old-project.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
title: Reviving an Old Project
|
||||||
|
description: Clippable and it's current future
|
||||||
|
date: 2025-08-19T21:26:49-07:00
|
||||||
|
draft: false
|
||||||
|
category: article
|
||||||
|
---
|
||||||
|
|
||||||
|
# Context
|
||||||
|
|
||||||
|
A while back I created [Clippable](https://git.shockrah.xyz/shockrah/clippable),
|
||||||
|
which was meant to be a way for me to share gaming clips with others because I
|
||||||
|
didn't like using streamable, youtube, etc. I'm still not a huge fan of it
|
||||||
|
especially considering I have the technical know how to build my own clip
|
||||||
|
sharing system/website.
|
||||||
|
|
||||||
|
Now that I'm once again looking for work :wink: I'm in a position where I
|
||||||
|
need to have a new "main" project to bring up in interviews & resumes.
|
||||||
|
My choice this time around of course is [Clippable](https://git.shockrah.xyz/shockrah/clippable)
|
||||||
|
which should provide ample room for me to _demonstrate_ my skills.
|
||||||
|
|
||||||
|
_Also I can actually use the end result which is nice_.
|
||||||
|
|
||||||
|
|
||||||
|
# What is it?
|
||||||
|
|
||||||
|
|
||||||
|
I'll be honest, it's a self-hosted streamable clone whose
|
||||||
|
front-end got a huge facelift and is now being packaged with Gitea.
|
||||||
|
|
||||||
|
# Now what?
|
||||||
|
|
||||||
|
Now comes the fun part which is packaging everything and updating docs
|
||||||
|
so that this can be fully presentable and remain as a proper "receipt"
|
||||||
|
of my skill because it's easier if my work can speak for itself in interviews :wink:
|
||||||
|
|
||||||
|
# Where?
|
||||||
|
|
||||||
|
The link to the project is here :link: https://git.shockrah.xyz/shockrah/clippable
|
||||||
|
|
||||||
|
Link to the docs is here :link: https://shockrah.gitlab.io/clippable/
|
||||||
117
content/posts/windows-grub-efi.md
Normal file
117
content/posts/windows-grub-efi.md
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
---
|
||||||
|
title: Fixing a windows EFI boot directory
|
||||||
|
description: Because I can't into Grub
|
||||||
|
date: 2023-10-27T18:27:05-07:00
|
||||||
|
image: /favicon.png
|
||||||
|
draft: false
|
||||||
|
category: article
|
||||||
|
---
|
||||||
|
|
||||||
|
# Context
|
||||||
|
|
||||||
|
After making my usual Debian drive unusable ( thanks Nvidia ) from an
|
||||||
|
`apt upgrade` I found myself re-installing Debian all over again. Luckily
|
||||||
|
I keep my `/home` and `/` mounted on separate partitions so this was
|
||||||
|
pretty easy. When it came time to pick a drive to boot off of however I comletely
|
||||||
|
forgot that I had a Windows drive that I had been using to jankily boot off of.
|
||||||
|
|
||||||
|
_Sidenote_: I only forgot because I never bothered to remedy the situation of
|
||||||
|
being forced to smack F12 9999 times every time I booted for a few months. :shrug:
|
||||||
|
|
||||||
|
After re-installing Debian and getting setup once more I went to boot into
|
||||||
|
Windows since I had some avatar modeling I wanted to do and.... couldn't boot.
|
||||||
|
|
||||||
|
# Discovering what happened
|
||||||
|
|
||||||
|
From Debian, check where the `/boot` is mounted to.
|
||||||
|
In my case I have drives `sda` and `sdb` which contain Debian and Windows data
|
||||||
|
respectively. I found the following
|
||||||
|
|
||||||
|
1. `/boot` was mounted to `sdb`
|
||||||
|
2. `/boot/efi/EFI/` did not contain any sort of Windows folder
|
||||||
|
|
||||||
|
:mag: **HINT:** there are tools in Debian repos to repair this folder however
|
||||||
|
I tested literally none so good luck.
|
||||||
|
|
||||||
|
Basically the new Grub installation had wiped out the old `/boot` partition
|
||||||
|
which I never paid attention to and removed it :facepalm: hence why it had
|
||||||
|
no Windows section. Normally an `update-grub` would suffice **if** that folder
|
||||||
|
was present but this was not enough.
|
||||||
|
|
||||||
|
# Solution
|
||||||
|
|
||||||
|
To make Windows bootable I setup a Windows installation USB drive using dd as such:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
dd if=/path/to/Windows.iso of=/dev/<usb-drive> status=progress
|
||||||
|
```
|
||||||
|
|
||||||
|
Also this will hang when it gets to the end but seriously just give it some time
|
||||||
|
because it basically has to verify everything after it's been copied over.
|
||||||
|
|
||||||
|
Finally I found this post on superuser which shows how to bring back the EFI
|
||||||
|
bootloader for windows so that Grub create a new entry for it and we can boot
|
||||||
|
like normal :arrow_right: [answer](https://superuser.com/a/1444266)
|
||||||
|
|
||||||
|
# Raw paste of Solution from 🌐 [superuser](https://superuser.com/a/1444266)
|
||||||
|
In case that answer ever gets clobbered here is the raw paste:
|
||||||
|
|
||||||
|
|
||||||
|
The other answers given here work great on MBR/BIOS systems, however if you're
|
||||||
|
on a UEFI system like I am, bootsect will just write a semi-functional boot MBR
|
||||||
|
over the [🌐 GPT protective MBR and bootrec](https://en.wikipedia.org/wiki/GUID_Partition_Table#Protective_MBR_(LBA_0))
|
||||||
|
just gives an "Access denied" error message, and neither one has a functional
|
||||||
|
option to fix a broken [🌐 EFI system partition](https://en.wikipedia.org/wiki/EFI_system_partition),
|
||||||
|
which on a UEFI/GPT drive is what
|
||||||
|
contains the bootloader that used to be stored in the MBR. There's unfortunately
|
||||||
|
almost no up-to-date guides on fixing the UEFI Windows Boot Manager (almost all
|
||||||
|
of them just say to run the graphical Startup Repair utility, but that doesn't
|
||||||
|
fix the problem in all cases), but I finally found the correct solution buried
|
||||||
|
in [🌐 this article](https://www.partitionwizard.com/clone-disk/bootrec-fixboot-access-is-denied.html),
|
||||||
|
which requires the use of the [🌐 bcdboot](https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/bcdboot-command-line-options-techref-di) command instead:
|
||||||
|
|
||||||
|
1. Grab the [🌐 Media Creation Tool](https://www.microsoft.com/en-us/software-download/windows10), make yourself a Windows 10 installation DVD or USB drive, and then boot into it.
|
||||||
|
|
||||||
|
2. When prompted, choose "Repair your computer", followed by "Troubleshoot", "Advanced Options", and finally "Command Prompt".
|
||||||
|
|
||||||
|
3. Run `diskpart` and then `list disk`. Note the disk number for the disk with your EFI system partition (ESP).
|
||||||
|
|
||||||
|
4. Select that disk with `select disk x` (where `x` is the disk number from the last step).
|
||||||
|
|
||||||
|
5. Run `list volume`. Note the volume number for your EFI system partition (ESP).
|
||||||
|
|
||||||
|
6. Now do `select volume x` (where `x` is the volume number for the ESP) and then
|
||||||
|
`assign letter=N:` to mount the partition. Run `list volume` again and note that
|
||||||
|
the ESP is now assigned a driver letter. Run `exit` to leave `diskpart`.
|
||||||
|
|
||||||
|
7. (Optional) If you are not currently dual booting and want to fully clean the
|
||||||
|
ESP before writing a new bootloader, run `format N: /FS:FAT32` to reformat it as
|
||||||
|
FAT32. This is probably not necessary under normal circumstances, however, as
|
||||||
|
`bcdboot` seems to do a good job of cleaning things up itself. Especially **do not
|
||||||
|
do this if you have a Linux distro on another partition** or else you'll have to
|
||||||
|
reinstall GRUB as well once you're done with this. Also note that the following
|
||||||
|
steps should not affect an EFI GRUB install as long as you do not otherwise
|
||||||
|
delete GRUB's existing directory on the ESP.
|
||||||
|
|
||||||
|
8. Finally, write the new bootloader to the partition with `bcdboot C:\windows /s N: /f UEFI`.
|
||||||
|
This command rebuilds a new UEFI-compatible bootloader on the ESP mounted at `N:`
|
||||||
|
using the Windows installation mounted at C:\windows. Once it's done, you can
|
||||||
|
verify the new bootloader was written by running `dir N:\EFI`, where you should
|
||||||
|
see a `Microsoft directory` containing the new Windows Boot Manager as well as a
|
||||||
|
`boot directory` containing the fallback bootloader (along with other directories
|
||||||
|
for any other bootloaders you have installed, such as GRUB for Linux).
|
||||||
|
|
||||||
|
9. (Optional) If you are dual booting, you will probably need to boot into your
|
||||||
|
Linux distro and run `sudo update-grub` to allow the GRUB scripts to detect and
|
||||||
|
add the new Windows bootloader.
|
||||||
|
|
||||||
|
10. Now boot into your BIOS setup and make sure "Windows Boot Manager" (or GRUB,
|
||||||
|
if you're dual-booting) is set as the top boot choice. Save and reboot and
|
||||||
|
you'll finally be back in Windows (or GRUB).
|
||||||
|
|
||||||
|
|
||||||
|
Here are some links to help you understand EFI stuff ( because I still don't )
|
||||||
|
|
||||||
|
* https://askubuntu.com/questions/1144636/three-questions-on-boot-efi-and-boot-mountpoints
|
||||||
|
* https://support.microsoft.com/en-us/topic/use-bootrec-exe-in-the-windows-re-to-troubleshoot-startup-issues-902ebb04-daa3-4f90-579f-0fbf51f7dd5d
|
||||||
7
scripts/compare.py
Normal file
7
scripts/compare.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import hashlib
|
||||||
|
|
||||||
|
with open('public/tags/index.xml') as file:
|
||||||
|
data = hashlib.sha1(file.read().encode('utf-8'))
|
||||||
|
|
||||||
|
remote = '99d66a9e171feaf11be88b831bc69c55d85c1b4b'
|
||||||
|
print(remote == data.hexdigest())
|
||||||
29
scripts/neocities.py
Normal file
29
scripts/neocities.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from os import environ
|
||||||
|
from requests import get
|
||||||
|
from json import dumps
|
||||||
|
|
||||||
|
def request(key: str, uri: str):
|
||||||
|
url = f'https://neocities.org{uri}'
|
||||||
|
headers = { 'Authorization': f'Bearer {key}' }
|
||||||
|
response = get(url, headers=headers)
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_new_content(key: str):
|
||||||
|
'''
|
||||||
|
Fetches a list of all files on neocities
|
||||||
|
'''
|
||||||
|
# First fetch the hashes of all our files
|
||||||
|
response = request(key, '/api/list')
|
||||||
|
remote_files = response['files']
|
||||||
|
|
||||||
|
# COmpare remote hashes to local hashes
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
key = environ.get('NEOCITIES_API_KEY')
|
||||||
|
if key is None:
|
||||||
|
print('Check to ensure NEOCITIES_API_KEY is set in the env vars')
|
||||||
|
exit(1)
|
||||||
|
else:
|
||||||
|
get_public_contents(key)
|
||||||
|
|
||||||
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
[[ "$1" = "" ]] && echo No filename given for new post\! && exit 1
|
[[ "$1" = "" ]] && echo No filename given for new post\! && exit 1
|
||||||
|
|
||||||
file="$(basename $1)"
|
name="$(basename -s .md $1)"
|
||||||
|
|
||||||
cat << EOF | tee content/posts/"$file.md"
|
echo Creating new post content/posts/$name.md with metadata:
|
||||||
|
cat << EOF | tee content/posts/"$name.md"
|
||||||
---
|
---
|
||||||
title: $(basename -s .md "$file")
|
title: $(basename -s .md "$file")
|
||||||
date: $(date '+%F')
|
date: $(date '+%F')
|
||||||
|
|||||||
1
static/.well-known/discord
Normal file
1
static/.well-known/discord
Normal file
@@ -0,0 +1 @@
|
|||||||
|
dh=1c0133027994b982e04807790b3a6a3925e368d8
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<meta property="og:video:width" content="640">
|
<meta property="og:video:width" content="640">
|
||||||
<meta property="og:video:height" content="480">
|
<meta property="og:video:height" content="480">
|
||||||
{{ else }}
|
{{ else }}
|
||||||
{{ $ogimage := "{{ .Site.BaseURL }}/favicon.png" }}
|
{{ $ogimage := printf "%s%s" .Site.BaseURL "/favicon.png" }}
|
||||||
{{ if .Params.Image }}
|
{{ if .Params.Image }}
|
||||||
{{ $ogimage = .Params.Image }}
|
{{ $ogimage = .Params.Image }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
Reference in New Issue
Block a user